NSubstitute完全手册(十一)参数匹配器

参数匹配器可以用于设置返回值检查接收到的调用。它提供了一种指定一个调用或一组调用的方式,这样可以对所有匹配的调用设置一个返回值,或者检查是否接收到了匹配的调用。

忽略参数

通过使用 Arg.Any<T>() 可以忽略一个T类型的参数。

 1     public interface ICalculator
 2     {
 3       int Add(int a, int b);
 4       string Mode { get; set; }
 5     }
 6 
 7     [TestMethod]
 8     public void Test_ArgumentMatchers_IgnoringArguments()
 9     {
10       var calculator = Substitute.For<ICalculator>();
11 
12       calculator.Add(Arg.Any<int>(), 5).Returns(7);
13 
14       Assert.AreEqual(7, calculator.Add(42, 5));
15       Assert.AreEqual(7, calculator.Add(123, 5));
16       Assert.AreNotEqual(7, calculator.Add(1, 7));
17     }

在这个例子中,我们设定当任意数与 5 相加时,返回值 7。我们使用 Arg.Any<int>() 来告诉 NSubstitute 忽略第一个参数。

我们也可以通过这种方法来匹配任意的子类型。
 1     public interface IFormatter
 2     {
 3       void Format(object o);
 4     }
 5 
 6     [TestMethod]
 7     public void Test_ArgumentMatchers_MatchSubTypes()
 8     {
 9       IFormatter formatter = Substitute.For<IFormatter>();
10 
11       formatter.Format(new object());
12       formatter.Format("some string");
13 
14       formatter.Received().Format(Arg.Any<object>());
15       formatter.Received().Format(Arg.Any<string>());
16       formatter.DidNotReceive().Format(Arg.Any<int>());
17     }

参数条件匹配

通过使用 Arg.Is<T>(Predicate<T> condition) 来对一个T类型的参数进行条件匹配。
 1     [TestMethod]
 2     public void Test_ArgumentMatchers_ConditionallyMatching()
 3     {
 4       var calculator = Substitute.For<ICalculator>();
 5 
 6       calculator.Add(1, -10);
 7 
 8       // 检查接收到第一个参数为1,第二个参数小于0的调用
 9       calculator.Received().Add(1, Arg.Is<int>(x => x < 0));
10       // 检查接收到第一个参数为1,第二个参数为 -2、-5和-10中的某个数的调用
11       calculator
12         .Received()
13         .Add(1, Arg.Is<int>(x => new[] { -2, -5, -10 }.Contains(x)));
14       // 检查未接收到第一个参数大于10,第二个参数为-10的调用
15       calculator.DidNotReceive().Add(Arg.Is<int>(x => x > 10), -10);
16     }

如果某参数的条件表达式抛出异常,则将假设该参数未被匹配,异常本身会被隐藏。

 1     [TestMethod]
 2     public void Test_ArgumentMatchers_ConditionallyMatchingThrowException()
 3     {
 4       IFormatter formatter = Substitute.For<IFormatter>();
 5 
 6       formatter.Format(Arg.Is<string>(x => x.Length <= 10)).Returns("matched");
 7 
 8       Assert.AreEqual("matched", formatter.Format("short"));
 9       Assert.AreNotEqual("matched", formatter.Format("not matched, too long"));
10 
11       // 此处将不会匹配,因为在尝试访问 null 的 Length 属性时会抛出异常,
12       // 而 NSubstitute 会假设其为不匹配并隐藏掉异常。
13       Assert.AreNotEqual("matched", formatter.Format(null));
14     }

匹配指定的参数 

使用 Arg.Is<T>(T value) 可以匹配指定的T类型参数。
 1     [TestMethod]
 2     public void Test_ArgumentMatchers_MatchingSpecificArgument()
 3     {
 4       var calculator = Substitute.For<ICalculator>();
 5 
 6       calculator.Add(0, 42);
 7 
 8       // 这里可能不工作,NSubstitute 在这种情况下无法确定在哪个参数上应用匹配器
 9       //calculator.Received().Add(0, Arg.Any<int>());
10 
11       calculator.Received().Add(Arg.Is(0), Arg.Any<int>());
12     }

通常来讲,这个匹配器不是必须的;大部分情况下,我们可以使用 0 来代替 Arg.Is(0)。然而在某些情况下,NSubstitute 无法解析出那个匹配器应用到了那个参数上(实际上,参数匹配器进行的是模糊匹配;而不是直接解析函数的调用)。在这些情况下会抛出一个 AmbiguousArgumentsException,并且会要求你指定一个或多个额外的参数匹配器。大多数情况下你可能不得不为每个参数显式的使用参数匹配器。

NSubstitute 完全手册

posted @ 2013-05-22 10:53  sangmado  阅读(1813)  评论(0编辑  收藏  举报