简体   繁体   English

Moq Lambda表达式表现异常

[英]Moq lambda expression behaving unexpectedly

I have a unit test using MOQ that's behaving unexpectedly. 我有一个使用最小起订量的单元测试,表现出乎意料。 I'm expecting the IsAuthorizedAsync method to always return true, but it's returning false. 我期望IsAuthorizedAsync方法始终返回true,但是返回false。 Here's a simplified version of the code that's adding the IsAuthorizedAsync method to my Mock Object. 这是将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;
   }

Here's code similar to the code that's using it: 这是与使用它的代码相似的代码:

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

Like I said, it's returning false when it looks to me like it should always return true. 就像我说的那样,当它看起来应该总是返回true时,它返回false。 Is there any way for me to step into the lambda expression code? 我有什么办法进入lambda表达式代码? Alternatively, is there any way for me to view what the actual lambda expression that's being used when I call this.mockObject.IsAuthorizedAsync? 另外,当我调用this.mockObject.IsAuthorizedAsync时,是否有任何方法可以查看正在使用的实际lambda表达式? I suspect it's not what I think it is. 我怀疑这不是我想的。

-Eric -Eric

As per @tzachs' comment, note that the It.IsIn matcher takes a list of matching values (strings in your instance). 根据@tzachs的评论,请注意It.IsIn匹配器采用匹配值(实例中的字符串)的列表。 It.IsIn() with an empty params or IEnumerable will never match anything, as it is implemented with .Contains : 带有空paramsIEnumerable It.IsIn()将永远不会匹配任何内容,因为它是通过.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)));
}

hence the failure to return the desired result. 因此无法返回预期的结果。 You'll want to either change this eg 您可能想要更改此,例如

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

Also, note that when working with Async methods, that Moq (and Test Frameworks like NUnit and XUnit) have support for Async semantics. 另外,请注意,使用Async方法时,Moq(以及诸如NUnit和XUnit的测试框架)都支持Async语义。 So instead of 'hacking' a Task.FromResult , what you can do instead is: 因此,代替“黑客” 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));
}

(and yes, I know I'm just testing the Mock here :) (是的,我知道我只是在这里测试Mock :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM