我应该把这个代码放在MVC中?

时间:2011-09-15 17:25:47

标签: unit-testing asp.net-mvc-3 logic

我的代码完美无缺,但是。在这种情况下最好的做法是什么?

以下是重要的代码。

这是在控制器中。

    private IProductRepository repository;
    [HttpPost]
    public ActionResult Delete(int productId) {
        Product prod = repository.Products.FirstOrDefault(p => p.ProductID == productId);
        if (prod != null) {
            repository.DeleteProduct(prod);
            TempData["message"] = string.Format("{0} was deleted", prod.Name);
        }
        return RedirectToAction("Index");
    }

这是存储库(接口等)

public interface IProductRepository {
    IQueryable<Product> Products { get; }
    void SaveProduct(Product product);
    void DeleteProduct(Product product);
}

这就是存储库.....(重要的部分)我想指出的是......这不是一个非常清楚的假类。测试是在假类上进行的。

    private EFDbContext context = new EFDbContext();

    public IQueryable<Product> Products {
        get { return context.Products; }
    }

    public void DeleteProduct(Product product) {
        context.Products.Remove(product);
        context.SaveChanges();
    }

第一个问题: 在对此进行测试时,我将在“ControllerTest”中在Controller上创建两个TestMethods。 “Can_delete_valid_product”和“Cannot_delete_invalid_product”。为存储库提供测试类是否有任何意义?像“RepositoryTest”一样,控制器会测试删除功能是否正常工作,不需要对它进行两次测试吗?

第二个问题: 在此我在控制器中测试产品是否存在,然后尝试删除它。如果它存在,我调用存储库中的deletefunction。这意味着永远不应该有例外的可能性。但是如果你向下发送null,你仍然可以在存储库中创建一个例外。 (这不可能发生在这里,但如果忘记检查是否为空,你仍然可以这样做)。问题是,如果产品存在的测试应该在存储库中完成吗?

3 个答案:

答案 0 :(得分:1)

我更倾向于在大多数情况下将逻辑排除在控制器之外。对控制器操作的测试将验证是否调用了存储库,但是在该测试中模拟了存储库本身。我会让存储库负责处理空检查。

答案 1 :(得分:0)

  

这意味着永远不应该有例外的可能性。但是如果你向下发送null,你仍然可以在存储库中创建一个例外。 (这不可能发生在这里,但如果忘记检查是否为null,你仍然可以这样做。)

或者,如果在检查它之后但在删除之前将其删除。或者,如果您失去与存储库的连接(或者在这种情况下方法永远不会返回?)。你不能以这种方式避免例外。

答案 2 :(得分:0)

  1. 我个人为我的存储库/数据访问创建单独的测试,以确保它正常工作。控制器本身将使用模拟进行测试。

  2. 实际上,有人可以删除某个产品,就像其他人试图删除它一样,这完全有可能(可能不是那么可能)。在这种情况下,您可能不关心/需要知道有人这样做但我可能只是在存储库中吞下该异常(尽管我会先记录它)。在空检查/防御性编程方面,这完全是个人选择。有些人将这样的支票留给系统的入口点,而其他人则会构建一个分层防御,在整个代码中都有额外的检查。问题是这些检查会变得非常难看,这是我希望Code Contracts获得更多牵引力的重要原因。