验证方法在 Action 中被调用

Verify that method is called within Action

这些天我一直在练习单元测试,所以如果我不了解一些基础知识,请多多包涵。

具有这些简单的抽象:

public interface ITaskFactory
{
    void StartTask(Action action);
}

internal sealed class TaskFactory : ITaskFactory
{
    public void StartTask(Action action)
    {
        Task.Factory.StartNew(action);
    }
}

和这个class来测试(简化为这种情况):

internal sealed class TriggerEventDecorator<TEvent> : ITriggerEvent<TEvent> where TEvent : IEvent
{
    private readonly ITaskFactory _taskFactory;
    private readonly Func<ITriggerEvent<TEvent>> _factory;

    public TriggerEventDecorator(ITaskFactory taskFactory, Func<ITriggerEvent<TEvent>> factory)
    {
        _taskFactory = taskFactory;
        _factory = factory;
    }

    public void Trigger(TEvent evt)
    {
        _taskFactory.StartTask(() =>
        {
            _factory().Trigger(evt);
        });
    }
}

我对此的测试 class:

public class TriggerEventDecoratorTests
{
    [Fact]
    public void CanTriggerEventHandler()
    {
        var evt = new FakeEventWithoutValidation();
        Assert.IsAssignableFrom<IEvent>(evt);

        var decorated = new Mock<ITriggerEvent<FakeEventWithoutValidation>>(MockBehavior.Strict);
        decorated.Setup(x => x.Trigger(evt));

        var taskFactory = new Mock<ITaskFactory>(MockBehavior.Strict);
        taskFactory.Setup(factory => factory.StartTask(It.IsAny<Action>()));

        var decorator = new TriggerEventDecorator<FakeEventWithoutValidation>(taskFactory.Object, () => decorated.Object);
        decorator.Trigger(evt);

        taskFactory.Verify(x => x.StartTask(It.IsAny<Action>()), Times.Once);
        decorated.Verify(x => x.Trigger(evt), Times.Once); // This line is not verified
    }
}

decorated.Verify(x => x.Trigger(evt), Times.Once); 未验证,从未被调用。

如何测试这是在 _taskFactoryAction 中触发的?

您没有调用 Func 方法。这就是问题所在...为此,您必须使用 Callback 方法。

更改以下设置:

taskFactory.Setup(factory => factory.StartTask(It.IsAny<Action>()));

收件人:

taskFactory.Setup(factory => factory.StartTask(It.IsAny<Action>()))
           .Callback<Action>((action) => action());