MVC 3: How to learn how to test NUnit, Ninject and Moq?

Short version of my questions:

  • Can someone point me to some good, detailed sources from which I can learn how to implement testing in my MVC 3 application using NUnit, Ninject 2, and Moq?
  • Can anyone here explain how the controller-repository decoupling, mockery and dependency injection work together?



Longer version of my questions:

What am I trying to do ...

I'm currently starting to create an MVC 3 application that will use Entity Framework 4 with a basic database approach. I want to do it right, so I'm trying to develop classes, layers, etc., to be highly verifiable. But I have little experience without unit testing or integration testing, except for an academic understanding of them.

After many studies, I decided to use

  • NUnit as a testing platform
  • Ninject 2 as my dependency injection infrastructure
  • Moq as my mocking structure.

I know which topic is best suited, etc., can enter into it, but at the moment I really don’t know enough about it to form a solid opinion. So, I just decided to go with these free solutions, which seemed to be very liked and well maintained.

What I have learned so far ...

I spent some time working on some of these materials by reading resources such as:

From these resources, I was able to figure out the need for a repository template, complete with repository interfaces, to separate my controllers and data access logic. I have already written some of them in my application, but I admit that I do not know about the mechanics of all this, and I am doing this in support of a mocking or dependent injection, or both. So, of course, I would not mind hearing from you guys about this too. Any clarity I can get about this will help me at this point.

Where everything got dirty for me ...

It seemed to me that I was well versed in this material until I started hugging Ninject, as described in Building Testable ASP.NET MVC Applications , cited above. In particular, I was completely lost at the moment when the author begins to describe the implementation of the service level, about half in the document.

In any case, now I am looking for more resources to study in order to try to get different perspectives around this material until it makes sense to me.

Summing up all this, throwing it to specific questions, I am interested in the following:

  • Can someone point me to some good, detailed sources from which I can learn how to implement testing in my MVC 3 application using NUnit, Ninject 2, and Moq?
  • Can anyone here explain how the controller-repository decoupling, mockery and dependency injection work together?

EDIT:

I just opened the official Ninject wiki on Github, so I'm going to start with this to find out if it will start clarifying things for me. But I'm still very interested in the thoughts of the SO community on all of this :)

+47
unit-testing nunit moq asp.net-mvc-3 ninject-2
Jul 11 2018-11-11T00:
source share
3 answers

If you are using the Ninject.MVC3 nuget package, then the part of the article that you linked that causes confusion is not required. This package has everything you need to start introducing your controllers, which is probably the biggest pain point.

After installing this package, he will create the NinjectMVC3.cs file in the App_Start folder, inside this class will be the RegisterServices method. Here you must 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; } } 

If you are after a very high testing coverage, then in principle at any time when one logical piece of code (for example, a controller) should talk with another (for example, a database), you should create an interface and implementation, add a definition binding to RegisterService and add a new constructor argument.

This applies not only to the controller, but also to any class, so in the above example, if you need a WebData instance for implementing the repository for something, you would add a readonly field and a constructor to your repository implementation.

Then, when it comes to testing, what you want to do is drop the version of all the necessary interfaces, so the only thing you are testing is the code in the method for which you are writing the test. So, in my example, let's say that IRepository has

 bool TryCreateUser(string username); 

called by the controller method

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

What you are actually trying to check here is that the if statement and return types you do not need to create a real repository that will return true or false based on the special values ​​you give it. Here you want to make fun.

 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"]); } 

^ This does not compile for you, since I know that xUnit is better, and I don't remember the property names in RedirectToActionResult from the top of the head.

So, to summarize, if you want one piece of code to talk to another, remove the interface between them. This allows you to make fun of the second piece of code so that during the first test you can control the output and be sure that you are testing only the corresponding code.
I think that it was precisely this moment that really made a penny for me with all this, you do not have to do this because it requires code, but because testing requires it.

One of the last tips specific to MVC is whenever you need to access core web objects, HttpContext, HttpRequest, etc., wrap them all behind the interface (like IWebData in my example), because, while you can mock these using * base classes, it becomes very painful because they have many internal dependencies that you also need to make fun of. Also use Moq to install MockBehaviour Strict when creating mocks, and it will tell you that something is called that you did not provide a layout for.

+59
Jul 11
source share
  • Here is the application that I am creating. It is open source and available on github and uses all the necessary materials - MVC3, NUnit, Moq, Ninject - https://github.com/alexanderbeletsky/trackyt.net/tree/master/src

  • Disassembling the Contoller-Repository is simple. All data operations are moved to the repository. A repository is an implementation of some type of IRepository. The controller never creates repositories inside itself (with the new operator), but rather accepts them either with a constructor argument or a property.

.

 public class HomeController { public HomeController (IUserRepository users) { } } 

This method is called "Inversion of Control." To support control inversion, you must provide some "Injection of Dependency" infrastructure. Ninject is a good one. Inside Ninject, you bind a specific interface to an implementation class:

 Bind<IUserRepository>().To<UserRepository>(); 

You will also replace the factory default controller with your own. Inside custom, you delegate a call to the Ninject core:

 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; } } 

When the MVC framework is about to create a new controller, the call is delegated to the user controller factory method GetControllerInstance, which delegates its Ninject. Ninject sees that to create this controller, the constructor has one argument of type IUserRepository . Using the declared binding, he sees that "I need to create a UserRepository to satisfy the needs of IUserRepository." It creates an instance and passes it to the constructor.

The constructor never knows which instance will be passed inside. It all depends on the binding you provide for this.

Code Examples:

+9
Jul 11 '11 at 6:25
source share

Watch: DDD Melbourne Video - New Development Workflow

The entire development process of ASP.NET MVC 3 was very well presented.

The third-party tools that I like the most:

  • Using NuGet to Install Ninject to Enable DI in the Entire MVC3 Framework
  • Using NuGet to install nSubstite to create mocks to enable block testing
+1
Jul 13 2018-11-11T00:
source share



All Articles