为什么这个测试单元通过?

时间:2011-01-14 00:17:35

标签: asp.net-mvc mocking nunit

我在这上花了2个多小时...我无法弄清楚为什么这个测试正在通过。我的意思是..它不应该返回视图“已完成”,但在测试中它确实如此!它说预期“string.Empty”但返回“已完成”但是对于信用卡要通过..安全码需要是“测试”,这在测试中根本不存在。所以它应该返回默认视图(类似于view();)。

我做错了什么?这是我的测试错了吗?还是控制器逻辑?

非常感谢。


[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;
    }
}

2 个答案:

答案 0 :(得分:1)

我找到了解决问题的方法。为了帮助其他可能有相同问题的人,我将解释它。

问题在于我的测试。由于mocks对象是没有方法的空对象,所以零逻辑。这意味着测试实际上不使用MainCreditCarDProcessor的实例。 (我不知道那个)

所以我必须通过添加:

来为这个特定的测试设置模拟
// Arrange: Given we have a creditcard processor that return TransactionDeclined.
mockCreditCardProcessor.SetReturnsDefault(TransactionResult.TransactionDeclined);

要强制它返回TransactionDeclined,通过这不是“强制”,因为它是一个模拟你只是将它设置为返回该值,否则我猜它会返回它找到的默认值..在这种情况下是0枚举的第一个元素,或者返回其他类型的方法的null。

如果我说错了,请纠正我。

感谢。

答案 1 :(得分:0)

如果ShouldBeDefaultView()抛出,测试将失败。