Moq lambda表达式行为异常

本文关键字:异常 表达式 lambda Moq | 更新日期: 2023-09-27 18:01:51

我有一个使用最小起订量的单元测试,它的行为出乎意料。我期望IsAuthorizedAsync方法总是返回真,但它返回假。下面是代码的简化版本,它将IsAuthorizedAsync方法添加到我的Mock对象。

    public static IAuthenticationInterface GetAuthentication()
    {
       var mock = new Mock<IAuthenticationInterface>();
       mock.Setup(e => e.IsAuthorizedAsync(It.IsIn<string>(), It.IsAny<MyEvent>())).Returns(System.Threading.Tasks.Task.FromResult(true)).Verifiable();
       // return the mock object
       return mock.Object;
   }

下面的代码与使用它的代码类似:

bool isAuthorized = this.mockObject != null && await this.mockObject.IsAuthorizedAsync("abc123", myEvent).ConfigureAwait(false);

就像我说的,当它看起来应该总是返回真时,它返回假。是否有任何方法让我进入lambda表达式代码?或者,是否有任何方法让我查看实际的lambda表达式,正在使用当我调用this.mockObject.IsAuthorizedAsync?我怀疑它不是我想的那样。

eric

Moq lambda表达式行为异常

根据@tzachs的评论,请注意It.IsIn匹配器接受匹配值的列表(在您的实例中是字符串)。It.IsIn()与空paramsIEnumerable将永远不会匹配任何东西,因为它是用.Contains实现的:

public static TValue IsIn<TValue>(IEnumerable<TValue> items)
{
   return Match.Create<TValue>((Predicate<TValue>) 
     (value => Enumerable.Contains<TValue>(items, value)), 
     (Expression<Func<TValue>>) (() => It.IsIn<TValue>(items)));
}

因此无法返回期望的结果。你可能想要改变这个,例如

It.IsAny<string>() // ... Any string at all
It.Is<string>(s => s == "Foo") // ... Match via a Predicate
It.IsIn<string>("Foo", "Bar", "Baz") // ... Match via a List

另外,请注意,当使用异步方法时,Moq(以及像NUnit和XUnit这样的测试框架)支持Async语义。所以,你可以做的不是"黑"一个Task.FromResult,而是:

[Test]
public async void MyTest()  // ... The UT can be made async
{
    var mock = new Mock<IAuthenticationInterface>();
    mock.Setup(e => e.IsAuthorizedAsync(It.IsIn<string>("Foo"), It.IsAny<MyEvent>()))
            .ReturnsAsync(true)  // ... Async
            .Verifiable();
    // async calls can be awaited
    Assert.True(await mock.Object.IsAuthorizedAsync("Foo", null));
}

(是的,我知道我只是在这里测试Mock:)