模拟功能<tin,tout>

时间:2019-03-16 23:15:33

标签: c# testing moq

我有一些用例,其中我将Funcs传递给某些方法。我正在尝试使用Moq创建扩展或帮助程序,该扩展程序或帮助程序使我的测试可以轻松创建函数。该帮助者的目标是

  1. 易于定义具有预期输入和固定输出的功能
  2. 如果未调用函数,则测试应失败
  3. 如果用错误的输入调用函数,测试应该失败
  4. 使用It.IsAny<TInput>()应该可以在任何模拟游戏中使用

我得到了我想要的大部分东西,但是第4项使我望而却步。这是扩展程序和带有我不明白的难以捉摸的失败测试的测试

public static Func<TIn, TOut> FixedFunc<TIn, TOut>(this MockRepository repo, TIn expectedInput, TOut fixedOutput)
{
    var verifier = repo.Create<IInvokable<TIn, TOut>>(MockBehavior.Strict);

    verifier.Setup(m => m.Invoke(expectedInput))
        .Returns(fixedOutput);

    return input => verifier.Object.Invoke(input);
}

public static Func<TIn, TOut> FixedFunc<TIn, TOut>(this MockRepository repo, TOut fixedOutput)
{
    var verifier = repo.Create<IInvokable<TIn, TOut>>(MockBehavior.Strict);

    verifier.Setup(m => m.Invoke(It.IsAny<TIn>()))
        .Returns(fixedOutput);

    return input => verifier.Object.Invoke(input);
}

public interface IInvokable<TIn, TOut>
{
    TOut Invoke(TIn input);
}

这里是测试

[Fact] // succeeds
public void MockFunc_SameObject_RetursResult()
{
    var expectedInput= new object();
    var expectedOutput = 2;

    var repo = new MockRepository(MockBehavior.Strict);
    var function = repo.FixedFunc(exptecedInput, expectedOutput);

    var output = function(expectedInput);
    Assert.Equal(expectedOutput, output);

    repo.VerifyAll();
}

[Fact]
// Fails with the following exception:
// "Moq.MockException: IInvokable`2.Invoke(object) invocation failed with mock behavior Strict.
// All invocations on the mock must have a corresponding setup."
public void MockFunc_IsAny_RetursResult()
{
    var exptecedInput = new object();
    var expectedOutput = 2;

    var repo = new MockRepository(MockBehavior.Strict);
    var function = repo.FixedFunc(It.IsAny<object>(), expectedOutput);

    var output = function(exptecedInput);
    Assert.Equal(expectedOutput, output);

    repo.VerifyAll();
}

[Fact] // succeeds
public void MockFunc_WithAny_RetursResult()
{
    var expectedOutput = 2;

    var repo = new MockRepository(MockBehavior.Strict);
    var function = repo.FixedFunc<object, int>(expectedOutput);

    var output = function(new object());
    Assert.Equal(expectedOutput, output);

    repo.VerifyAll();
}

我不明白It.IsAny对于FixedFunc <TOut>的工作原理,但不适用于FixedFunc <TIn, TOut>

1 个答案:

答案 0 :(得分:0)

请注意,如果您评估It.Any<object>(),结果将是null。对于Func<TIn, TOut>,您正在有效地创建以下设置:

verifier.Setup(m => m.Invoke(null)).Returns(fixedOutput);

,然后使用var exptecedInput = new object();进行调用。在VerifyAll期间,moq尝试求值并匹配参数时,由于null != new object(),它无法这样做。


您也可以使用It.Any<object>()调用方法,或者重新设计扩展以传递Expression并使用Expression而不是特定对象注册设置。

[Fact] // This will pass
public void MockFunc_IsAny_RetursResult()
{
    var expectedOutput = 2;

    var repo = new MockRepository(MockBehavior.Strict);
    var function = repo.FixedFunc(It.IsAny<object>(), expectedOutput);

    var output = function(It.IsAny<object>());

    Assert.Equal(expectedOutput, output);
    repo.VerifyAll();
}