我正在尝试对“服务层”/“应用程序外观层”方法进行单元测试.这是我试图进行单元测试的方法:
// Create a new order in the database for a customer.  Given a customer id,// will create a new order and return an OrderDto for use in the presentation
// layer.
public OrderDto CreateOrderForCustomer(int customerId)
{
  // Find the customer
  var customer = _customerRepository.GetCustomerById(customerId);

  // Create an order and apply special logic to get it ready for use.
  var orderFactory = new OrderFactory();
  var order = orderFactory.CreateOrder(customer);

  // IMPORTANT: This is what I'm trying to unit test ...
  _orderRepository.Save(order);

  order.Status = "Editing";

  // Using AutoMapper to turn this into a DTO that will be returned
  // to the Presentation layer.  The Mappings are created in the 
  // constructor and not depicted in this code snippet.
  var orderDto = Mapper.Map<Order,OrderDto>(order);

  return orderDto;
}

(注意……为了清楚起见,我在这里添加了大量的注释.我通常不会这么说.)

由于这个方法的工作是编排域层方法和持久层方法来创建一个空订单,坚持下去,并将其作为一个简单的DTO返回,我认为这对FakeItEasy来说是一个很棒的工作……我只是确保那些关键方法正在精心编排,确保使用FakeItEasy的MustHaveHappened()调用它们.

所以,考虑到这一点,这是我创建的单元测试:

[TestMethod]
public void CreateOrderForCustomer_ValidCustomer_CreatesNewOrder()
{
  // Arrange
  var customer = _customerRepository.GetCustomerById(1);
  Assert.AreEqual(0,customer.Orders.Count);

  // Act
  var orderDto = _orderEntryService.CreateOrderForCustomer(1);

  // Assert

  // Here I'm trying to make sure to re-create the order that was actually 
  // sent into the _customerRepository.Save() ... I should be able to
  // simple un-map the OrderDto back to an Order,and undo the property 
  // change.
  var order = Mapper.Map<OrderDto,Order>(orderDto);
  order.Status = "New";

  A.CallTo(() => _customerRepository.GetCustomerById(1)).MustHaveHappened();

  // **THIS CAUSES AN EXCEPTION**
  A.CallTo(() => _orderRepository.Save(order)).MustHaveHappened();
  Assert.AreEqual(1,customer.Orders.Count);
}

在单元测试中,我无法访问在测试方法中创建的ACTUAL Order,我尝试做下一个最好的事情…通过被测方法返回订单的DTO版本,map订单的DTO版本返回到域模型Order的新实例,并确保属性相同,然后再将其发送到FakeItEasy的MustHaveHappened().

我已经调试了单元测试并且看到了ACTUAL Order的属性而不是FAKED Order的属性……我向你保证,它们是相同的.此外,我可以通过调试确认_customerRepository.Save(order)确实被调用.


是.MustHaveHappened()失败,因为我实际上是在发送Order对象的两个不同实例 – 即使它们的属性是相同的?即使属性相同,FakeItEasy是否需要输入参数的相同实例才能确保方法调用已经发生?

此外,关于我应该如何测试这种事情的任何建议(即,编排/服务/“应用程序外观”/你想要调用它的层方法)?

解决方法

Is .MustHaveHappened() failing because I’m essentially sending in two different instances of the Order object — even though their properties are identical?

是. FakeItEasy将使用.Equals,它(除非你的类重写它)引用类型默认为引用相等.

(…) does FakeItEasy need the same instance of the input parameter to ensure that the method call has happened?

不.您可以像这样进行自定义参数匹配:

A.CallTo(() => _orderRepository.Save(A<Order>.That.Matches(o =>
    o.Status == "New" &&
    o.Id == 10
))).MustHaveHappened();

但是,这个问题揭示了您的代码存在问题.从您的示例中可以清楚地看出,您正在将_customerRepository注入依赖项.那很棒.你为什么不对OrderFactory做同样的事情?如果它是通过接口/基类依赖注入的,那么你可以轻松地模拟(假)它并且你当前的问题不会存在.

如果你可以改变你的代码,我建议注射工厂(遵循简单的指导方针 – “没有新闻是好消息!”).如果没有,请使用自定义匹配器验证订单属性,就像我在上面的示例中所做的那样.

c# – FakeItEasy说MustHaveHappened并没有发生……但确实如此的更多相关文章

  1. 如何在iOS中为预期的assert / assertionFailure编写单元测试?

    这里的问题是,当someString参数为空字符串时,您可以保证函数不会失败–在您的实际应用程序中.这是因为断言不在发布版本中运行.结果是你可以在开发过程中使用assert作为调试的一种形式,但如果这种情况在现实生活中发生,你应该按顺序处理它,而不是崩溃.因此测试断言“发生”是否真的不是一种有效的单元测试技术,这就是为什么你以这种方式使用它的麻烦.

  2. ios – 核心数据并发调试:假阳性

    如WWDC2014session225(核心数据新增内容)所述,iOS8和OSX优胜美地的核心数据现在支持命令行参数-com.apple.CoreData.ConcurrencyDebug1,以启用检测到违反CoreData的并发合同的断言.在我的实验中,我发现它在iOS8beta1(在设备和模拟器中)都可以工作,但是我似乎发现了一个错误的肯定,即框架是抛出一个多线程违规异常不这样做至少这是我的信

  3. swift 断言(assert)

    和OC断言用法一样,只不过方法名去掉"NS"就可以了.断言可以让你程序在不满足断言条件时崩溃到断言处.当你的程序对参数有严格要求时,可以使用断言对参数进行检查.而且断言可以在release版本中配置去掉.

  4. Swift入门四——可选类型Optionals与断言Assert

    String和Int类型对应的可选类型分别是String?等可选类型的变量值均可以为nil。然而强制解封一个值为nil的可选类型会导致运行时错误。可选绑定Swift是一门简洁的语言,使用强制类型解封来获取可选类型变量里的值过于麻烦,是很多人不愿意使用的。所以在使用隐式可选类型变量时,为了安全起见,还是应该用if语句进行判断。附录查看完整专栏——《Swift轻松入门》

  5. 2.Swift 中的assert

    在Swift中,自带了一个断言的方法,其中的断言可选为带断言信息,有的可选为不带断言信息,下面让我们来看看.下面让我们来看看一个简单的小例子PS:assert分为两个参数,一个是condition,为bool值,为true不会断言,为false就会断言,后面的message是一个可选的错误信息,如果需要的话,就可以使用,不需要的也可以直接不写.再者,我们可以把判断条件放在condition里面去,

  6. Swift可选绑定、断言

    可选绑定可以用在if和while语句中来对可选类型的值进行判断并把值赋给一个常量或者变量。断言可选类型可以让你判断值是否存在,你可以在代码中优雅地处理值缺失的情况。此外,断言允许你附加一条调试信息。然而,在你的应用发布之前,有时候非法条件可能出现,这时使用断言可以快速发现问题。

  7. Swift中assert(断言)的使用

    在Swift中,通过assert实现断言,assert可以帮助开发者比较容易的发现和定位错误一个断言断定条件是true.通过声明一个断言来确保某个必要的条件是满足的,以便继续执行接下来的代码。代码注意点断言可以引发程序终止,并不是被设计用来避免不在发生无效情况的。

  8. Swift 断言 assert

    断言Optionals使得我们可以检测值是否存在。在这些情况下,可以使用触发断言来终止执行并提供调试。断言是在运行时检测条件是否为true,如果为true,就继续往下执行,否则就在这里中断。

  9. swift3 assert断言

    在Swift中,通过assert实现断言,assert可以帮助开发者比较容易的发现和定位错误。一个断言断定条件是true.通过声明一个断言来确保某个必要的条件是满足的,以便继续执行接下来的代码。例:如果断言被触发,将会强制结束程序,并打印相关信息:assertionFailed:number不大于3:file/Users/mac/Desktop/test/test/ViewController.swift,line17注意点:断言可以引发程序终止,并不是被设计用来避免不在发生无效情况的。

  10. 保护 Equatable 的实现

    如果忘记的话,Equatable的一致性就会被打破,这个bug多久会被发现取决于测试的质量——这里编译器无法提供任何帮助。我查看了一些标准库中的Swift类型以及Apple原生框架中的类,这些类型都遵守了Equatable协议,它们与dump的用法配合的很好。结论或许你可以使用linter、静态分析工具、像Sourcery这样的代码生成工具或者其他的什么方法来保护Equatable的实现,避免回顾代码。assertDumpsEqual的功能实现依托于标准库中的assert函数。

随机推荐

  1. c# – (wpf)Application.Current.Resources vs FindResource

    所以,我正在使用C#中的WPF创建一个GUI.它看起来像这样:它现在还没有完成.这两行是我尝试制作一种数据表,它们在XAML中是硬编码的.现在,我正在C#中实现添加新的水果按钮功能.我在XAML中有以下样式来控制行的背景图像应该是什么样子:因此,在代码中,我为每列col0,col1和col2创建一个图像,如果我使用以下代码,它添加了一个如下所示的新行:如你所见,它不太正确……为什么一个似乎忽略了一些属性而另一个没有?

  2. c# – 绑定DataGridTemplateColumn

    似乎我已经打了个墙,试图在DataGrid上使用DataTemplates.我想要做的是使用一个模板来显示每个单元格的两行文本.但是似乎无法以任何方式绑定列.以下代码希望显示我想做的事情.注意每个列的绑定:模板列没有这样的东西,因此,这个xaml不可能工作.我注定要将整个DataTemplate复制到每个列,只是对每个副本都有不同的约束?解决方法我不完全确定你想要做什么,但如果您需要获取整行的DataContext,可以使用RelativeSource绑定来移动视觉树.像这样:

  3. c# – 学习设计模式的资源

    最近我来到了这个设计模式的概念,并对此感到非常热情.你能建议一些帮助我深入设计模式的资源吗?

  4. c# – 是否有支持嵌入HTML页面的跨操作系统GUI框架?

    我想开发一个桌面应用程序来使用跨系统,是否有一个GUI框架,允许我为所有3个平台编写一次代码,并具有完全可脚本化的嵌入式Web组件?我需要它有一个API来在应用程序和网页之间进行交流.我知道C#,JavaScript和一些python.解决方法Qt有这样的事情QWebView.

  5. c# – 通过字符串在对象图中查找属性

    我试图使用任意字符串访问嵌套类结构的各个部分.给出以下(设计的)类:我想要从Person对象的一个实例的“PersonsAddress.HousePhone.Number”获取对象.目前我正在使用反思来做一些简单的递归查找,但是我希望有一些忍者有更好的想法.作为参考,这里是我开发的(crappy)方法:解决方法您可以简单地使用标准的.NETDataBinder.EvalMethod,像这样:

  6. c# – 文件下载后更新页面

    FamilyID=0a391abd-25c1-4fc0-919f-b21f31ab88b7&displaylang=en&pf=true它呈现该页面,然后使用以下元刷新标签来实际向用户提供要下载的文件:你可能需要在你的应用程序中做类似的事情.但是,如果您真的有兴趣在文件完全下载后执行某些操作,那么您的运气不佳,因为没有任何事件可以与浏览器进行通信.执行此操作的唯一方法是上传附件时使用的AJAXupload.

  7. c# – 如何在每个机器应用程序中实现单个实例?

    我必须限制我的.net4WPF应用程序,以便每台机器只能运行一次.请注意,我说每个机器,而不是每个会话.我使用一个简单的互斥体实现单实例应用程序,直到现在,但不幸的是,这样一个互斥是每个会话.有没有办法创建机器互连,还是有其他解决方案来实现每个机器应用程序的单个实例?

  8. c# – WCF和多个主机头

    我的雇主网站有多个主机名,都是同一个服务器,我们只是显示不同的皮肤来进行品牌宣传.不幸的是,在这种情况下,WCF似乎不能很好地工作.我试过overridingthedefaulthostwithacustomhostfactory.这不是一个可以接受的解决方案,因为它需要从所有主机工作,而不仅仅是1.我也看过thisblogpost,但是我无法让它工作,或者不是为了解决我的问题.我得到的错误是“这

  9. c# – ASP.NET MVC模型绑定与表单元素名称中的虚线

    我一直在搜索互联网,试图找到一种方式来容纳我的表单元素的破折号到ASP.NET的控制器在MVC2,3或甚至4中的默认模型绑定行为.作为一名前端开发人员,我更喜欢在我的CSS中使用camelCase或下划线进行破折号.在我的标记中,我想要做的是这样的:在控制器中,我会传入一个C#对象,看起来像这样:有没有办法通过一些正则表达式或其他行为来扩展Controller类来适应这种情况?我讨厌这样的事实,我必须这样做:甚至这个:思考?

  10. c# – 用户界面设计工具

    我正在寻找一个用户界面设计工具来显示文档中可能的GUI.我不能生成代码.我知道MicrosoftVisio提供了一个功能.但有什么办法吗?您使用哪种软件可视化GUI?

返回
顶部