【问题标题】:Why use It.is<> or It.IsAny<> if I could just define a variable?如果我可以定义一个变量,为什么要使用 It.is<> 或 It.IsAny<>?
【发布时间】:2016-08-31 06:53:20
【问题描述】:

您好,当我看到这段代码时,我已经使用 moq 有一段时间了。

我必须在我的一个回购中设置回报。

 mockIRole.Setup(r => r.GetSomething(It.IsAny<Guid>(), It.IsAny<Guid>(), 
                  It.IsAny<Guid>())).Returns(ReturnSomething);

我有三个参数,我只是在网上的一篇文章或博客中看到这些。

It.Is&lt;&gt;It.IsAny&lt;&gt; 对对象有什么用?如果我可以使用Guid.NewGuid() 或其他类型,那么为什么要使用It.Is

很抱歉,我不确定我的问题是否正确,或者我是否缺少一些测试知识。 不过好像都没什么问题。

【问题讨论】:

  • It.IsAny&lt;Guid&gt;() 表示您不关心传递了什么参数。 Guid.NewGuid() 表示您希望设置方法以仅在第一个参数等于此新 GUID 时才返回。
  • 我不知道你在问什么。 Moq 是说,只要传入正确的类型,调用就有效并且应该返回您的对象。
  • It.Is&lt;&gt; 有助于确保您使用参数中的正确值调用依赖项
  • 我见过初级开发人员尝试使用It.IsAny&lt;int&gt;() 为测试用例生成变量。它不起作用 :) 我还看到很多懒惰的测试编写者使用It.IsAny 来处理所有事情,因为他们无法弄清楚要使用的实际变量..

标签: c# unit-testing testing mocking moq


【解决方案1】:

使用It.IsAny&lt;&gt;It.Is&lt;&gt; 或变量都有不同的用途。在设置或验证方法时,它们提供了越来越具体的方法来匹配参数。

It.IsAny

​​>

使用It.IsAny&lt;&gt; 设置的方法将匹配您提供给该方法的任何 参数。因此,在您的示例中,以下调用都将返回相同的内容 (ReturnSomething):

role.GetSomething(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid());

Guid sameGuid = Guid.NewGuid();
role.GetSomething(sameGuid, sameGuid, sameGuid);

role.GetSomething(Guid.Empty, Guid.NewGuid(), sameGuid);

传递的Guid 的实际值无关紧要。

它是

It.Is&lt;&gt; 构造对于设置或验证方法很有用,可让您指定与参数匹配的函数。例如:

Guid expectedGuid = ...
mockIRole.Setup(r => r.GetSomething(
                 It.Is<Guid>(g => g.ToString().StartsWith("4")), 
                 It.Is<Guid>(g => g != Guid.Empty), 
                 It.Is<Guid>(g => g == expectedGuid)))
         .Returns(ReturnSomething);

这允许您限制该值,而不仅仅是任何值,但允许您对您接受的内容宽容。

定义变量

当您使用变量设置(或验证)方法参数时,您是在说您想要完全该值。使用另一个值调用的方法永远不会匹配您的设置/验证。

Guid expectedGuids = new [] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
mockIRole.Setup(r => r.GetSomething(expectedGuids[0], expectedGuids[1], expectedGuids[2]))
         .Returns(ReturnSomething);

现在只有一种情况,GetSomething 将返回 ReturnSomething:当所有 Guids 与您设置的预期值匹配时。

【讨论】:

  • 这确实是我需要的。我认为定义和使用确实是另一回事。只是 it.is 可以灵活地接受参数。
  • 谢谢,这很有帮助,将添加到有关 Mock 的文档中。
  • 嗨,Patrick,关于您的回答,您能在stackoverflow.com/questions/52854915/… 中进一步向我解释我的问题吗?最初我将一个变量传递给我的验证方法,但它失败了。但是,当我更改它并通过 It.IsAny 时,它反而通过了。我是单元测试的新手,所以我仍然很难理解这一点。
【解决方案2】:

如果你看Quickstart documentation for Moq

匹配参数

// any value
mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Returns(true);


// matching Func<int>, lazy evaluated
mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true); 


// matching ranges
mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns(true); 


// matching regex
mock.Setup(x => x.DoSomething(It.IsRegex("[a-d]+", RegexOptions.IgnoreCase))).Returns("foo");

【讨论】:

  • 如果我们不关心传入的 any 参数怎么办?想象一个有四个或更多参数的方法,它会变得很长。
猜你喜欢
  • 1970-01-01
  • 2017-01-17
  • 1970-01-01
  • 2019-03-10
  • 2020-11-14
  • 2014-09-05
  • 1970-01-01
  • 2012-01-13
相关资源
最近更新 更多