问题
I spend over 2 hours on this... i can't figure out why this test is PASSING. I mean.. it shouldnt return the view "Completed" but in the test it does! It say Expected "string.Empty" but returned "Completed" however for the creditcard to pass.. the securitycode need to be "test" which is isnt at all in the test. So it should return the default view (which is like view();).
What i am doing wrong ? it is my test that is wrong ? or the controller logic ?
Thanks a lots.
[Test]
public void Cannot_Check_Out_If_Credit_Card_Failed_To_Process()
{
var mockOrderSubmitter = new Mock<IOrderSubmitter>();
var mockCreditCardProcessor = new Mock<ICreditCardProcessor>();
// Arrange: Given a user has a non-empty cart
var cart = new Cart();
cart.AddItem(new Product(), 1);
// Arrange: ... but the credit card failed to process
var cartController = new CartController(null, mockOrderSubmitter.Object, mockCreditCardProcessor.Object);
var result = cartController.CheckOut(cart, new ShippingDetails(), new CreditCard() { SecurityCode = "123" });
// Assert
result.ShouldBeDefaultView();
}
[HttpPost]
public ActionResult CheckOut(Cart cart, ShippingDetails shippingDetails, CreditCard creditCard)
{
// Empty carts can't be checked out
if (cart.Lines.Count == 0)
ModelState.AddModelError("Cart", "Sorry, your cart is empty!");
// Everything is valid
if (ModelState.IsValid)
{
// Effectue le paiement.
TransactionResult result = creditcardProcessor.TakePayment(creditCard, cart.ComputeTotalValue());
if (result == TransactionResult.Success)
{
// Envoi la commande
orderSubmitter.SubmitOrder(cart, shippingDetails);
cart.Clear();
return View("Completed");
}
else
{
ModelState.AddModelError("CreditCard", "Sorry, we couldn't process your credit card, please verify your credit card details and retry.");
return View(new CheckOutViewModel());
}
}
else // Something was invalid
return View(new CheckOutViewModel());
}
public class MainCreditCardProcessor : ICreditCardProcessor
{
public TransactionResult TakePayment(CreditCard card, decimal amount)
{
if (card.SecurityCode == "test")
return TransactionResult.Success;
else
return TransactionResult.TransactionDeclined;
}
}
回答1:
I found a solution to my problem. To help others poeple that might have the same problem i will explain it.
The problem was with my test. Since mocks objects are empty objects with no methods inside, zero logics. That mean that the test actually doesn't use an instance of the MainCreditCarDProcessor. (I didn't know about that)
So i had to setup the mock for this particular test by adding :
// Arrange: Given we have a creditcard processor that return TransactionDeclined.
mockCreditCardProcessor.SetReturnsDefault(TransactionResult.TransactionDeclined);
To force it to return TransactionDeclined,, through this is not "forcing" since its a mock you just set it up to return that value otherwise i guess it will return the default value it find.. which in this case was 0 the first element of the enum or null for other kind of method that return others kind of values.
If anything i said is wrong please correct me.
Thanks.
回答2:
The test will fail if ShouldBeDefaultView()
throws.
来源:https://stackoverflow.com/questions/4686814/why-is-this-test-unit-pass