【问题标题】:Moq lambda expression behaving unexpectedlyMoq lambda 表达式行为异常
【发布时间】:2015-07-08 14:11:42
【问题描述】:

我有一个使用 MOQ 的单元测试,其行为异常。我期望 IsAuthorizedAsync 方法始终返回 true,但它返回 false。这是将 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);

就像我说的,当它看起来应该总是返回 true 时,它​​返回 false。我有什么办法可以进入 lambda 表达式代码吗?或者,有什么方法可以让我查看调用 this.mockObject.IsAuthorizedAsync 时使用的实际 lambda 表达式?我怀疑这不是我想的那样。

-埃里克

【问题讨论】:

  • 使用 Visual Studio 2013,我可以进入 lambda 表达式。只需在表达式上放置断点后使用 step in (f11)。
  • 这对我来说看起来不错,并且在我设置类似的东西时工作,所以我认为设置不完全正确或发生了其他事情 - myEvent 的类型是什么?这绝对是 MyEvent 吗?
  • 你是在模拟一个接口还是一个类?如果是类,方法是否标记为虚拟?
  • e 在第一个代码中 sn-p 是一个接口。在第二个 sn-p 中,myEvent 是 MyEvent 返回 true。
  • 您可能有错字吗? It.IsIn&lt;string&gt;() 应该是 It.IsAny&lt;string&gt;() 吧?

标签: c# unit-testing lambda mocking moq


【解决方案1】:

根据@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

另外,请注意,在使用 Async 方法时,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 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-19
    • 2011-12-21
    • 1970-01-01
    • 2017-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多