在 运行 单元测试时验证作为参数传递给注入接口时对 Func 的调用

Verifying calls to Func when passed as a parameter to an injected interface when running a unit test

我不确定在调用 Func 时验证方法是否被调用的最佳方法。使用下面的代码 - 我想确保注入的 IThirdPartyWrapper 在注入的 IInjectedInterface 上调用 DoSomething。有其他选择吗?

    [Test]
    public void Test()
    {
        var thirdPartyWrapperMock = new Mock<IThirdPartyWrapper>();
        var injectedInterface = new Mock<IInjectedInterface>();
        injectedInterface.Setup(x => x.DoSomething()).Verifiable();

        bool called = false;
        thirdPartyWrapperMock.Setup(x => x.Execute(It.IsAny<Func<Context, IInjectedInterface>>(), It.IsAny<Dictionary<string, object>>())).Callback(() =>
            {
                called = true;
            });

        var tester = new ConsumerClass(thirdPartyWrapperMock.Object, injectedInterface.Object);

        tester.Execute();

        // The below call fails
        injectedInterface.VerifyAll();
        // called is false
        Assert.True(called);

    }

    public class ConsumerClass
    {
        private readonly IThirdPartyWrapper _thirdPartyWrapper;
        private readonly IInjectedInterface _injectedInterface;

        public ConsumerClass(IThirdPartyWrapper thirdPartyWrapper, IInjectedInterface injectedInterface)
        {
            _thirdPartyWrapper = thirdPartyWrapper;
            _injectedInterface = injectedInterface;
        }

        public void Execute()
        {
            _thirdPartyWrapper.Execute(x => _injectedInterface.DoSomething(), new Dictionary<string, object>());
        }
    }


    public interface IThirdPartyWrapper
    {
        TResult Execute<TResult>(
            Func<Context, TResult> action,
            IDictionary<string, object> contextData);
    }

    public interface IInjectedInterface
    {
        string DoSomething();
    }

为了能够验证 Func,您需要从 Callback 调用它。尝试这样设置:

thirdPartyWrapperMock
    .Setup(x => x.Execute(It.IsAny<Func<Context, string>>(), It.IsAny<IDictionary<string, object>>()))
    .Callback<Func<Context, string>, IDictionary<string, object>>((func, dict) => func.Invoke(new Context()));

与原来的方法相比,您会注意到一些不同之处:

  • 函数的return值为string因为DoSomething()returnsstring.
  • 函数在回调中实际调用过,否则无法验证。 Context 根本不重要,因为您没有使用它。
  • 使用此设置不再需要 called,因为 VerifyAll 将确保调用该方法。