It.IsAny<Cart>(), It.IsAny<ShippingDetails>(), Times.Never(). What do they do?
I wonder if you could help me understand the following line:
mock.Verify(m => m.ProcessOrder(It.IsAny<Cart>(),
It.IsAny<ShippingDetails>()),
Times.Never());
The test method:
[TestMethod]
public void Cannot_Checkout_Empty_Cart()
{
// Arrange - create a mock order processor
开发者_高级运维 Mock<IOrderProcessor> mock = new Mock<IOrderProcessor>();
// Arrange - create an empty cart
Cart cart = new Cart();
// Arrange - create shipping details
ShippingDetails shippingDetails = new ShippingDetails();
// Arrange - create an instance of the controller
CartController target = new CartController(null, mock.Object);
// Act
ViewResult result = target.Checkout(cart, shippingDetails);
// Assert - check that the order hasn't been passed on to the processor
mock.Verify(m => m.ProcessOrder(It.IsAny<Cart>(), It.IsAny<ShippingDetails>()), Times.Never());
// Assert - check that the method is returning the default view
Assert.AreEqual("", result.ViewName);
// Assert - check that we are passing an invalid model to the view
Assert.AreEqual(false, result.ViewData.ModelState.IsValid);
}
It.IsAny<Cart>
matches any value of type Cart. Since you have Times.Never
, you actually verify that the method has never been called with the two parameters (Card, ShippingDetails).
@Wiktor has it right, but just to clarify the difference.
The current check is making sure that the method has not been called with ANY cart or ANY shipping details. This might seem excessive, as perhaps this might be sufficient:
// Assert - check that the order hasn't been passed on to the processor
mock.Verify(m => m.ProcessOrder(cart, shippingsDetails), Times.Never());
after all it is probable that the processing will be done with the given cart and shipping details. However it is possible that the cart could have been cloned, or some shipping details could have been loaded from the users preferences or something, and the It.IsAny<T>
allows you to check that the method was not called regardless of the arguments, as otherwise the verification would only happen with those specific instances as arguments.
EDIT
To answer the comment. Imagine another test where instead you wanted to check that the order was processed, and that it was processed with the correct arguments and not with some different users cart and shipping details:
// Arrange - create an empty cart
Cart cart = new Cart();
// Arrange - create shipping details
ShippingDetails shippingDetails = new ShippingDetails();
// Arrange - create an instance of the controller
CartController target = new CartController(null, mock.Object);
// Act
ViewResult result = target.Checkout(cart, shippingDetails);
//Assert - check the order was processed once with the
//correct cart and shipping details
mock.Verify(m => m.ProcessOrder(cart, shippingDetails), Times.Once());
now this tests fails if the ProcessOrder
method is not called with exactly the same cart and shipping details that was expected. If it happened to use another users cart or shipping details then the test would fail.
Hope this clear up the difference between specifying the arguments explicitly and using It.IsAny<T>
It is verifying that the method ProcessOrder
was never called using any type of Cart
and ShippingDetails
as arguments during the test.
精彩评论