Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 4.0 具有可测试性的C#MVC实体框架_C# 4.0_Asp.net Mvc 4 - Fatal编程技术网

C# 4.0 具有可测试性的C#MVC实体框架

C# 4.0 具有可测试性的C#MVC实体框架,c#-4.0,asp.net-mvc-4,C# 4.0,Asp.net Mvc 4,我正在考虑一些关于可测试性的“最佳实践”,以及定义特定操作的最佳方法 在SportsStore应用程序(来自Pro ASP.NET MVC 4)中,对于AdminController,我们在AdminController.cs文件中有以下两种方法: IPProductRepository namespace SportsStore.Domain.Abstract { public interface IProductRepository { IQueryable<

我正在考虑一些关于可测试性的“最佳实践”,以及定义特定操作的最佳方法

在SportsStore应用程序(来自Pro ASP.NET MVC 4)中,对于AdminController,我们在AdminController.cs文件中有以下两种方法:

IPProductRepository

namespace SportsStore.Domain.Abstract {
    public interface IProductRepository {

        IQueryable<Product> Products { get; }

        void SaveProduct(Product product);  //Defined in EFProductRepository

        void DeleteProduct(Product product);  //Defined in EFProductRepository
    }
}
正如我所注意到的,我们基本上在做相同的逻辑,即查找productID。如果productId发生了任何变化,那么我们需要在两个地方进行更改。但是,这可以很容易地进行测试,因为控制器本身正在进行Linq调用

我想我可以把它放到EFProducts的等价物中(因此IPProducts接口的数据库实现),但这会与某种数据库状态建立联系。我希望在单元测试中避免这种情况,因为它会增加测试的复杂性

有没有更好的地方来放置FindOrDefault逻辑,而不是在控制器中,同时保持良好的可测试性


Edit1:添加存储库的定义,它指向一个接口

我问题下的回答讨论了可能性。book和@maess都同意在控制器中保留此特定部分的逻辑。我的问题下的评论值得一看,因为@SOfanatic和@Maess都提供了非常好的输入。

因为您似乎在使用存储库,所以您应该在存储库中有一个名为
FindById(int Id)
的方法,然后您从控制器使用该方法,而不是每次都执行
FirstOrDefault
。我不认为存储库是非常有趣的测试方式。它要么工作要么不工作,最多可以在1个单元测试中涵盖这一点。我的建议是将代码移动到业务层并在那里进行测试。如果您使用的是IRepository和DI,您可以模拟存储库。感谢您的反馈@SOfanatic—将其添加到存储库中的唯一问题是测试时我与数据库的关系。在上面添加了更多的代码,希望能更清楚地说明这本书在做什么。将单元测试与数据库的状态联系起来会增加很多复杂性。@Maess-也感谢您的反馈。是的,这本书就是这么写的。逻辑在业务层是重复的,而这本身就是让我担心的。从“最佳实践”的角度来看,我不确定这是否正确。在Rails中,我注意到大多数业务逻辑都在模型中,而不是控制器中。也许C#中更常见的约定是控制器中有更多的逻辑?依我看,逻辑应该驻留在控制器使用的业务层,比如服务层。控制器应该只关心将正确的数据路由到视图,并处理进入给定操作的数据。Maess建议将逻辑从控制器中取出并放入服务层,而SOfanatic建议将逻辑从控制器中取出并放入存储库。在这两种情况下,都不应将逻辑留在控制器中。就像在Rails中一样,逻辑应该在模型(服务层/存储库)中,而不是在控制器中。
private IProductRepository repository;

public ViewResult Edit(int productId) {
    Product product = repository.Products.FirstOrDefault(p => p.ProductID == productId);
       ...
    }

[HttpPost]
public ActionResult Delete(int productId) {
        Product prod = repository.Products.FirstOrDefault(p => p.ProductID == productId);
        ...
    }