简体   繁体   English

如何在不使用存储库模式的情况下对 ASP.NET MVC Controller 进行单元测试

[英]How to unit test ASP.NET MVC Controller without Using Repository Pattern

I am just wondering if there a way I can unit test some of my controller Action in MVC without using Repository pattern.我只是想知道是否有一种方法可以在不使用存储库模式的情况下在 MVC 中对我的一些 controller 操作进行单元测试。 I have develop an ASP.NET MVC site but did this without unit testing at the initial stage.我开发了一个 ASP.NET MVC 站点,但在初始阶段没有进行单元测试。 Now I want to demonstrate some unit test to my tutor using may be two or more action in my controller. Most of my actions logic get data from database and one controller get data from different tables ie actions in one controller read from different table.现在我想用我的 controller 中的两个或更多动作向我的导师演示一些单元测试。我的大部分动作逻辑从数据库获取数据,一个 controller 从不同的表中获取数据,即一个 controller 中的动作从不同的表中读取。 which I think that can be test using Generic Repository pattern.我认为可以使用通用存储库模式进行测试。 As a beginner I found that I can only unit test a code that is not coming from database but unfortunately most of the code in my controller Actions come from database.作为初学者,我发现我只能对不是来自数据库的代码进行单元测试,但不幸的是,我的 controller Actions 中的大部分代码都来自数据库。 i am using the default test tool in visual Studio and EF code first approach for my database.我在我的数据库中使用 Visual Studio 中的默认测试工具和 EF 代码优先方法。
for example i will like to unit test only the below Actions without having to unit test other action that are in the same controller.例如,我只想对以下操作进行单元测试,而不必对同一 controller 中的其他操作进行单元测试。

public ActionResult Index()
    {
        var model = _db.PhotoGallery;
        return View(model);
    }

This is just for demonstration purpose.这仅用于演示目的。

By definition, a unit test should only affect the method that it calls.根据定义,单元测试应该只影响它调用的方法。 If you can find a way to mock your _db object so that you're not actually causing a database round-trip, then you can unit test this method that relies on it.如果你能找到一种方法来模拟你的 _db object 这样你实际上不会导致数据库往返,那么你可以对依赖它的这个方法进行单元测试。 Otherwise, no.否则,不。

Is your _db field's type an interface?您的_db字段类型是接口吗? Is it being provided via injection?它是通过注射提供的吗? If so, it's likely that you can unit test this method.如果是这样,您很可能可以对该方法进行单元测试。

Without removing the direct dependency to the database in you controller methods you will not be able to unit test these methods.如果不删除 controller 方法中对数据库的直接依赖,您将无法对这些方法进行单元测试。

The overall recommended way of doing this would be using an IOC Container (eg Ninject ) in combination with MVC that allows you to pass the data you need to the constructor of your controller. That "data object" must not be tied to the database, typically it is either just a POCO object or passed as an interface.这样做的总体推荐方法是将 IOC 容器(例如Ninject )与 MVC 结合使用,使您可以将所需的数据传递给 controller 的构造函数。该“数据对象”不得绑定到数据库,通常它只是一个 POCO object 或作为接口传递。

In your unit tests you can then substitute these dependencies using an in-memory data object constructed just for your unit tests, typically "mocked" using a mocking framework (eg Rhino Mocks or Moq ).在您的单元测试中,您可以使用专为您的单元测试构造的内存数据 object 替换这些依赖项,通常使用 mocking 框架(例如 Rhino Mocks 或Moq )“模拟”。

Using this approach you not only make your controllers unit-testable but also will end up with very loosely coupled code, a benefit that might pay off for later development.使用这种方法,您不仅可以使您的控制器可以进行单元测试,而且最终会得到非常松散耦合的代码,这种好处可能会在以后的开发中得到回报。

That's what called testable code:) When you perform unit testing, you need to be sure, that only reason of failing test is changing in SUT (system under test, or class being tested) implementation.这就是所谓的testable代码:) 当您执行单元测试时,您需要确定,测试失败的唯一原因是在 SUT(被测系统,或 class 正在测试)实现中发生变化。 Of course, it could be broken when dependency API changes (thats OK, you should modify SUT to use new API), but it never should fail if dependency implementations changed.当然,当依赖 API 发生变化时它可能会被破坏(没关系,你应该修改 SUT 以使用新的 API),但如果依赖实现发生变化它永远不会失败。 Thats why mocking and stubbing used.这就是为什么使用 mocking 和存根。

But if you want to mock dependency, you should not create it inside SUT.但是如果你想模拟依赖,你不应该在 SUT 中创建它。 It should be injected into SUT (constructor, property of parameter injection).它应该被注入到 SUT(构造函数,参数注入的属性)。

So, back to your case:所以,回到你的情况:

  • if you want to have testable class, you have to inject dependency (db)如果你想拥有可测试的 class,你必须注入依赖(db)
  • dependency should be mocked依赖应该被嘲笑
  • you not forced to use Repository pattern.您没有被迫使用存储库模式。 If you can mock your db class, just mock it.如果你可以模拟你的数据库 class,就模拟它。 Or use any other data access abstraction或者使用任何其他数据访问抽象

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM