我正在尝试对“服务层” / “应用程序门面层”方法进行单元测试。 这是我要进行单元测试的方法:
// 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;
}
(Note ... 为了更清晰地表述,我在这里添加了大量注释。我通常不会这么啰嗦。)
由于这种方法的工作是将领域层方法和持久层方法编排成创建一个空订单、将其持久化并将其作为简单的 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版本的订单,将该订单的DTO版本映射回一个新的领域模型Order实例,并确保属性相同,然后将其发送到FakeItEasy的MustHaveHappened()函数。
我调试了单元测试并查看了实际订单的属性与虚假订单的属性......我向您保证,它们是相同的。此外,通过调试,我可以确认_customerRepository.Save(order)确实被调用了。
问题:MustHaveHappened()失败是否因为我基本上发送了两个不同的订单对象实例 - 即使它们的属性是相同的?即使属性相同,FakeItEasy是否需要相同的输入参数实例来确保方法调用已发生?
此外,有什么建议可以测试这种类型的东西(即编排/服务/“应用程序外观”/任何你想称呼的层方法)吗?