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.