Unit testing MVC 3:如何学习如何使用NUnit、Ninject和Moq进行测试?
我的问题的简短版本:Unit testing MVC 3:如何学习如何使用NUnit、Ninject和Moq进行测试?,unit-testing,asp.net-mvc-3,nunit,moq,ninject-2,Unit Testing,Asp.net Mvc 3,Nunit,Moq,Ninject 2,我的问题的简短版本: 有人能告诉我一些好的,详细的资料来源吗 可以学习如何在我的MVC 3应用程序中使用 努尼特、尼尼特2号和莫克 这里有人能帮我澄清一下控制器存储库是如何工作的吗 解耦、模拟和依赖注入一起工作 我的问题的较长版本: 我想做什么… 我目前正在开始创建一个MVC3应用程序,它将使用EntityFramework4,采用数据库优先的方法。我想把这件事做好,所以我正在尝试设计类、层等,使其具有高度的可测试性。但是,除了对单元测试或集成测试有学术上的理解之外,我几乎没有单元测试或集成测
我的问题的较长版本: 我想做什么… 我目前正在开始创建一个MVC3应用程序,它将使用EntityFramework4,采用数据库优先的方法。我想把这件事做好,所以我正在尝试设计类、层等,使其具有高度的可测试性。但是,除了对单元测试或集成测试有学术上的理解之外,我几乎没有单元测试或集成测试的经验 经过大量研究,我决定使用
- NUnit作为我的测试框架
- Ninject 2作为我的依赖注入框架
- Moq作为我的模拟框架
new
操作符),而是通过构造函数参数或属性接收存储库Bind<IUserRepository>().To<UserRepository>();
当MVC基础结构即将创建新控制器时,调用被委托给定制控制器工厂GetControllerInstance方法,该方法将其委托给Ninject。Ninject发现,要创建该控制器,构造函数有一个类型为IUserRepository
的参数。通过使用声明的绑定,它看到“我需要创建一个UserRepository来满足IUserRepository的需要。”它创建实例并将其传递给构造函数
构造函数永远不知道将在内部传递什么样的实例。这完全取决于您为此提供的绑定
代码示例:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IRepository>().To<MyRepositoryImpl>();
kernel.Bind<IWebData>().To<MyWebDAtaImpl>();
}
如果您正在进行非常高的测试覆盖率,那么基本上只要一个逻辑代码段(比如控制器)需要与另一个逻辑代码段(比如数据库)对话,您就应该创建一个接口和实现,将定义绑定添加到RegisterService,并添加一个新的构造函数参数
这不仅适用于控制器,而且适用于任何类,因此在上面的示例中,如果您的存储库实现需要某个WebData实例,那么您可以将readonly字段和构造函数添加到存储库实现中
然后,当涉及到测试时,您要做的是提供所有必需接口的模拟版本,这样您要测试的唯一内容就是编写测试的方法中的代码。在我的例子中,我假设
public class TrackyControllerFactory : DefaultControllerFactory
{
private IKernel _kernel = new StandardKernel(new TrackyServices());
protected override IController GetControllerInstance(
System.Web.Routing.RequestContext requestContext,
Type controllerType)
{
if (controllerType == null)
{
return null;
}
return _kernel.Get(controllerType) as IController;
}
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IRepository>().To<MyRepositoryImpl>();
kernel.Bind<IWebData>().To<MyWebDAtaImpl>();
}
public class HomeController : Controller {
private readonly IRepository _Repo;
private readonly IWebData _WebData;
public HomeController(IRepository repo, IWebData webData) {
_Repo = repo;
_WebData = webData;
}
}
bool TryCreateUser(string username);
public ActionResult CreateUser(string username) {
if (_Repo.TryCreateUser(username))
return RedirectToAction("CreatedUser");
else
return RedirectToAction("Error");
}
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"]);
}