MVC 3:如何学会如何与NUnit的,Ninject和起订量测试? [英] MVC 3: How to learn how to test with NUnit, Ninject, and Moq?

查看:108
本文介绍了MVC 3:如何学会如何与NUnit的,Ninject和起订量测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

短版我的问题:


  1. 任何人都可以点我对一些很好的,详细的来源从中我
    可以学习如何在我的MVC 3应用程序中实现测试,使用
    NUnit的,Ninject 2,起订量和?

  2. 任何人都可以在这里帮助阐明我怎么控制器 - 库
    脱钩,嘲讽和依赖注入一起工作?

加长版我的问题:

我试图做...

我目前开始创建一个MVC 3应用程序,它使用实体框架4,与数据库的第一种方法。我想这样做的权利,所以我想设计的类,层等,要高度可测试。但是,我没有什么比他们的学术理解单元测试和集成测试,其他的没有经验。

I am currently beginning to create an MVC 3 application, which will use Entity Framework 4, with a database first approach. I want to do this right, so I am trying to design the classes, layers, etc., to be highly testable. But, I have little to no experience with unit testing or integration testing, other than an academic understanding of them.

在大量的研究,我已经解决使用

After lots of research, I've settle on using


  • NUnit的我的测试框架

  • Ninject 2 作为我的依赖注入框架

  • 起订量我的模拟框架。

  • NUnit as my testing framework
  • Ninject 2 as my dependency injection framework
  • Moq as my mocking framework.

我知道的话题,其中框架是最好的,等等,可以进入到这一点,但在这一点上,我真的不知道有足够的了解它的任何形成固体的意见。所以,我决定去与这些免费的解决方案,似乎也喜欢和良好的维护。

I know the topic of which framework is best, etc., could enter into this, but at this point I really don't know enough about any of it to form a solid opinion. So, I just decided to go with these free solutions which seem to be well liked and well maintained.

我学到的东西至今...

我花了一些时间,通过一些这方面的东西的工作,阅读资源,如:

I've spent some time working through some of this stuff, reading resources such as:

从这些资源,我已经成功地锻炼需要一个存储库模式,完整的资料库接口,以我的解耦控制器和我的数据访问逻辑。我已经写了一些那到我的应用程序了,但我承认我并不清楚整个事情的力学,我是否支持嘲讽,或依赖注入,或两者做这种脱钩。因此,我当然不会介意你这个家伙太听。任何清晰度我能获得这个东西会帮助我在这一点上。

From these resources, I've managed to workout the need for a Repository pattern, complete with repository interfaces, in order to decouple my controllers and my data access logic. I have written some of that into my application already, but I admit I am not clear as to the mechanics of the whole thing, and whether I am doing this decoupling in support of mocking, or dependency injection, or both. As such, I certainly wouldn't mind hearing from you guys about this too. Any clarity I can gain on this stuff will help me at this point.

的东西在哪里,我得到了泥泞...

我想我抓住了这个东西pretty很好,直到我开始试图总结我的周围Ninject头,在的建筑可测试ASP.NET MVC应用程序,上面提到。具体来说,我得到了完全失去了围绕在笔者开始描述服务层的实现,大约有一半的方式进入该文件的位置。

I thought I was grasping this stuff pretty well until I started trying to wrap my head around Ninject, as described in Building Testable ASP.NET MVC Applications, cited above. Specifically, I got completely lost around the point in which the author begins describing the implementation of a Service layer, about half way into the document.

无论如何,我现在正在寻找更多的资源来研究,以试图解决这个东西,不同的角度,直到它开始道理给我。

Anyway, I am now looking for more resources to study, in order to try to get various perspectives around this stuff until it begins to make sense to me.

总结这一切,煮下来到具体问题,我想知道以下内容:

Summarizing all of this, boiling it down to specific questions, I am wondering the following:


  1. 任何人都可以点我对一些很好的,详细的来源从中我
    可以学习如何在我的MVC 3应用程序中实现测试,使用
    NUnit的,Ninject 2,起订量和?

  2. 任何人都可以在这里帮助阐明我怎么控制器 - 库
    脱钩,嘲讽和依赖注入一起工作?

编辑:

我刚刚发现Github上 Ninject官方维基的,所以我要开始通过合作,看是否它开始澄清事情对我来说。但是,我仍然在SO社会思考这一切很感兴趣:)

I just discovered the Ninject official wiki on Github, so I'm going to start working through that to see if it starts clarifying things for me. But, I'm still very interested in the SO community thoughts on all of this :)

推荐答案

如果您使用的是 Ninject.MVC3 的NuGet包,那么一些文章您链接,是造成混乱不会被要求。这包有你需要开始注入你的控制器这可能是最大的痛点的一切。

If you are using the Ninject.MVC3 nuget package, then some of the article you linked that was causing confusion will not be required. That package has everything you need to start injecting your controllers which is probably the biggest pain point.

一旦安装该软件包,它会创建在App_Start文件夹中的文件NinjectMVC3.cs,内部的类是RegisterServices方法。这是你应该创建接口和你的实现之间的绑定

Upon installing that package, it will create a NinjectMVC3.cs file in the App_Start folder, inside that class is a RegisterServices method. This is where you should create the bindings between your interfaces and your implementations

private static void RegisterServices(IKernel kernel)  
{  
  kernel.Bind<IRepository>().To<MyRepositoryImpl>();
  kernel.Bind<IWebData>().To<MyWebDAtaImpl>();
}        

现在在你的控制器就可以使用构造注入。

Now in your controller you can use constructor injection.

public class HomeController : Controller {  
    private readonly IRepository _Repo;
    private readonly IWebData _WebData;

    public HomeController(IRepository repo, IWebData webData) {
      _Repo = repo;
      _WebData = webData;
    }
}

如果你是非常高的测试覆盖率后,那么基本上随时一张价值$ C $的c逻辑片(比如控制器)需要与另一个(比如数据库),你应该创建一个接口和实现中,添加定义绑定RegisterService并添加了新的构造函数的参数。

If you are after very high test coverage, then basically anytime one logical piece of code (say controller) needs to talk to another (say database) you should create an interface and implementation, add the definition binding to RegisterService and add a new constructor argument.

这不仅适用于控制器,但任何一类,所以在上面的例子中,如果你的仓库实现需要WEBDATA的实例的东西,你会在只读字段和构造函数添加到您的仓库实现。

This applies not only to Controller, but any class, so in the example above if your repository implementation needed an instance of WebData for something, you would add the readonly field and the constructor to your repository implementation.

然后当它涉及到的测试,你想要做的是提供所有所需的界面嘲笑版本,所以要测试的唯一事情是在你写的测试方法code。所以在我的例子,说IRepository有一个

Then when it comes to testing, what you want to do is provide mocked version of all required interfaces, so that the only thing you are testing is the code in the method you are writing the test for. So in my example, say that IRepository has a

bool TryCreateUser(string username);

这是由一个控制器的方法称为

Which is called by a controller method

public ActionResult CreateUser(string username) {
    if (_Repo.TryCreateUser(username))
       return RedirectToAction("CreatedUser");
    else
       return RedirectToAction("Error");
}

你真正想在这里测试的是,如果语句和返回类型,你不希望有创建一个真正的资源库,将根据你给它特殊的值返回true或false。这是要嘲笑。

What you are really trying to test here is that if statement and the return types, you do not want to have to create a real repository that will return true or false based on special values you give it. This is where you want to mock.

public void TestCreateUserSucceeds() {
    var repo = new Mock<IRepository>();
    repo.Setup(d=> d.TryCreateUser(It.IsAny<string>())).Returns(true);
    var controller = new HomeController(repo);
    var result = controller.CreateUser("test");
    Assert.IsNotNull(result);
    Assert.IsOfType<RedirectToActionResult>(result)
    Assert.AreEqual("CreatedUser", ((RedirectToActionResult)result).RouteData["Action"]);
}

^这不会编译你我所知的xUnit更好,并且不会从我的头顶记得RedirectToActionResult属性名。

^ That won't compile for you as I know xUnit better, and do not remember the property names on RedirectToActionResult from the top of my head.

所以,总结一下,如果你想一件code的交谈另外,在重击之间的接口。这就可以让你嘲笑第二件code,所以,当你考第一,你可以控制输出,并确保你有问题测试只有code。结果
我认为这是这一点上,真正与这一切都取得了一分钱都不降对我来说,你做这个不一定becase的在code需求,但因为测试需要它。

So to sum up, if you want one piece of code to talk to another, whack an interface in between. This then allows you to mock the second piece of code so that when you test the first you can control the output and be sure you are testing only the code in question.
I think it was this point that really made the penny drop for me with all this, you do this not necessarily becase the code demands it, but because the testing demands it.

具体到MVC,您需要访问基本的Web对象的任何时间的最后一个忠告,HttpContext的,Htt的prequest等,包装所有的这些接口后,以及(如IWebData在我的例子),因为当你可以使用*基类嘲笑这些,它就会变得疼痛非常迅速,因为他们有很多还需要模拟内部依赖的。结果
还与起订量,设置MockBehaviour严格创建嘲笑的时候,它会告诉你,如果任何被调用,你有没有对提供的模拟。

One last piece of advice specific to MVC, any time you need to access the basic web objects, HttpContext, HttpRequest etc, wrap all these behind an interface as well (like the IWebData in my example) because while you can mock these using the *Base classes, it becomes painful very quickly as they have a lot of internal dependencies you also need to mock.
Also with Moq, set the MockBehaviour to Strict when creating mocks and it will tell you if anything is being called that you have not provided a mock for.

这篇关于MVC 3:如何学会如何与NUnit的,Ninject和起订量测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆