I'm reading a book on Unit Testing, below is the quote and the code (not full code since it is easy to understand what the code does)
First, the author shows a mocking that doesn't lead to fragile tests:
[Fact]
public void Successful_purchase() {
var mock = new Mock<IEmailGateway>();
var sut = new CustomerController(mock.Object);
bool isSuccess = sut.Purchase(customerId: 1, productId: 2, quantity: 5);
Assert.True(isSuccess);
mock.Verify(x => x.SendReceipt("customer@email.com", "Shampoo", 5), Times.Once);
}
the author says:
The call to the SMTP service is a legitimate reason to do mocking. It doesn’t lead to test fragility because you want to make sure this type of communication stays in place even after refactoring. The use of mocks helps you do exactly that.
Then the author shows another example that leads to fragile tests:
[Fact]
public void Purchase_succeeds_when_enough_inventory() {
var storeMock = new Mock<IStore>();
storeMock.Setup(x => x.HasEnoughInventory(Product.Shampoo, 5)).Returns(true);
var customer = new Customer();
bool success = customer.Purchase(storeMock.Object, Product.Shampoo, 5);
Assert.True(success);
storeMock.Verify(x => x.RemoveInventory(Product.Shampoo, 5), Times.Once);
}
and the author says:
Unlike the communication between CustomerController and the SMTP service, the RemoveInventory() method call from Customer to Store doesn't cross the application boundary: both the caller and the recipient reside inside the application. Also, this method is neither an operation nor a state that helps the client achieve its goals.
I'm a little bit confused here, so we shouldn't test whether RemoveInventory is called? what happen the developer doesn't write the Purchase method correctly, which causes RemoveInventory method not being called on the IStore object, so the purchase will still success but the internal state is corrupted?
