博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NSubstitute完全手册(十七)参数匹配器上的操作
阅读量:7082 次
发布时间:2019-06-28

本文共 4674 字,大约阅读时间需要 15 分钟。

除了,当替代实例接收到了匹配的调用时,参数匹配器还可以用于执行特定的操作,并指定操作参数。这是一个相当罕见的需求,但在某些情况下可以使测试程序变得简单一些。

警告:一旦我们为替代实例添加有意义的行为,我们的测试和代码将面临过度指定和紧耦合的风险。对于类似的测试,通过抽象来更好地封装行为可能是更好的选择,甚至可以使用真实的协作对象并切换至 coarser-grained 测试。

调用回调函数

假设被测试类需要调用一个依赖对象的方法,并为其提供了一个回调函数,当依赖对象调用结束时通过回调来通知该类。当替代实例被调用时,我们可以使用 Arg.Invoke() 来立即调用这个回调。

让我们来看一个例子。比如说我们要测试 OrderPlacedCommand,其需要使用 IOrderProcessor 来处理订单,当处理成功地完成时使用 IEvents 来引发事件通知。

1     public interface IEvents 2     { 3       void RaiseOrderProcessed(int orderId); 4     } 5  6     public interface ICart 7     { 8       int OrderId { get; set; } 9     }10 11     public interface IOrderProcessor12     {13       void ProcessOrder(int orderId, Action
orderProcessed);14 }15 16 public class OrderPlacedCommand17 {18 IOrderProcessor orderProcessor;19 IEvents events;20 public OrderPlacedCommand(IOrderProcessor orderProcessor, IEvents events)21 {22 this.orderProcessor = orderProcessor;23 this.events = events;24 }25 public void Execute(ICart cart)26 {27 orderProcessor.ProcessOrder(28 cart.OrderId,29 wasOk => { if (wasOk) events.RaiseOrderProcessed(cart.OrderId); }30 );31 }32 }

在测试中,可以使用 Arg.Invoke() 来模拟 IOrderProcessor 处理订单结束的情况,并调用回调函数来通知调用方已经处理结束。

1     [TestMethod] 2     public void Test_ActionsWithArgumentMatchers_InvokingCallbacks() 3     { 4       // Arrange 5       var cart = Substitute.For
(); 6 var events = Substitute.For
(); 7 var processor = Substitute.For
(); 8 cart.OrderId = 3; 9 // 设置 processor 当处理订单ID为3时,调用回调函数,参数为true10 processor.ProcessOrder(3, Arg.Invoke(true));11 12 // Act13 var command = new OrderPlacedCommand(processor, events);14 command.Execute(cart);15 16 // Assert17 events.Received().RaiseOrderProcessed(3);18 }

这里我们构造了 processor,用于处理 ID 为 3 的订单,并调用回调函数。我们使用 Arg.Invoke(true) 来传递 true 给回调函数。

Arg.Invoke 有几个重载方法,可以用于调用参数数量和类型不同的回调函数。我们也可以使用 Arg.InvokeDelegate 来调用定制的委托类型(那些不只是简单的 Action 类型的委托)。

执行带参数的操作

有时我们可能不想立即就调用回调函数。或者可能我们想存储所有的实例到一个特殊的参数,并将该参数传递给一个方法。甚至我们只是想捕获某个参数,以便后期查看。我们可以使用 Arg.Do 来完成这些目的。Arg.Do 会为每个匹配的调用来执行给定参数的操作。

1     public interface ICalculator 2     { 3       int Multiply(int a, int b); 4     } 5  6     [TestMethod] 7     public void Test_ActionsWithArgumentMatchers_PerformingActionsWithArgs() 8     { 9       var calculator = Substitute.For
();10 11 var argumentUsed = 0;12 calculator.Multiply(Arg.Any
(), Arg.Do
(x => argumentUsed = x));13 14 calculator.Multiply(123, 42);15 16 Assert.AreEqual(42, argumentUsed);17 }

这里,Multiply 方法的第一个参数可为任意值,第二个参数将被传递值一个 argumentUsed 变量。当我们想断言某参数的多个属性时,这个功能是非常有用的。

1     [TestMethod] 2     public void Test_ActionsWithArgumentMatchers_PerformingActionsWithAnyArgs() 3     { 4       var calculator = Substitute.For
(); 5 6 var firstArgsBeingMultiplied = new List
(); 7 calculator.Multiply(Arg.Do
(x => firstArgsBeingMultiplied.Add(x)), 10); 8 9 calculator.Multiply(2, 10);10 calculator.Multiply(5, 10);11 12 // 由于第二个参数不为10,所以不会被 Arg.Do 匹配13 calculator.Multiply(7, 4567); 14 15 CollectionAssert.AreEqual(firstArgsBeingMultiplied, new[] { 2, 5 });16 }

在此例中,当调用 Multiply 方法第二个参数是 10 时,不管第一个 int 类型的参数的值是多少,Arg.Do 都会将其添加到一个列表当中。

参数操作和调用指定参数

就像 Arg.Any<T>() 一样,当参数的类型为 T 时,参数操作会调用一个指定操作(所以也可以用于和)。它只是多了个能与匹配指定规格的调用的参数交互的功能。

1     [TestMethod] 2     public void Test_ActionsWithArgumentMatchers_ArgActionsCallSpec() 3     { 4       var calculator = Substitute.For
(); 5 6 var numberOfCallsWhereFirstArgIsLessThan0 = 0; 7 8 // 指定调用参数: 9 // 第一个参数小于010 // 第二个参数可以为任意的int类型值11 // 当此满足此规格时,为计数器加1。12 calculator13 .Multiply(14 Arg.Is
(x => x < 0),15 Arg.Do
(x => numberOfCallsWhereFirstArgIsLessThan0++)16 ).Returns(123);17 18 var results = new[] {19 calculator.Multiply(-4, 3),20 calculator.Multiply(-27, 88),21 calculator.Multiply(-7, 8),22 calculator.Multiply(123, 2) // 第一个参数大于0,所以不会被匹配23 };24 25 Assert.AreEqual(3, numberOfCallsWhereFirstArgIsLessThan0); // 4个调用中有3个匹配上26 CollectionAssert.AreEqual(results, new[] { 123, 123, 123, 0 }); // 最后一个未匹配27 }

NSubstitute 完全手册

本文转自匠心十年博客园博客,原文链接:http://www.cnblogs.com/gaochundong/archive/2013/05/22/nsubstitute_actions_with_argument_matchers.html,如需转载请自行联系原作者
你可能感兴趣的文章
Python中如何实现im2col和col2im函数(sliding类型)
查看>>
IP校验shell脚本
查看>>
软件工程——《你的灯亮着吗》读书笔记
查看>>
Android平台刷机包制作研究(1)
查看>>
wamp下修改mysql root用户的登录密码方法
查看>>
怎样使用1M的内存排序100万个8位数
查看>>
Spark 性能相关參数配置具体解释-任务调度篇
查看>>
oracle 10g/11g RAC 启停归档模式
查看>>
MongoDB 删除数据库
查看>>
Centos6 Nginx安装
查看>>
python 11 函数名 迭代器
查看>>
oracle归档日志管理
查看>>
两个链表的第一个公共节点
查看>>
类代码
查看>>
js的闭包原理理解
查看>>
Android AIDL 一探究竟
查看>>
P问题、NP问题和NPC问题
查看>>
vmwear导出OVF模板解析(解决ovf导入服务器失败问题,虚拟机版本等)
查看>>
Nginx 的两种认证方式
查看>>
mysql连表分组报错---- sql_mode=only_full_group_by问题解决
查看>>