I am building a Prism 4 app, and I use the ServiceLocator to instantiate objects. The ServiceLocator is causing unit testing problems, and that leads me to wonder whether I should go back to injecting the IoC container into each class that needs it.
Here is an example of the problem from a repository base class:
protected RepositoryBase(string filePath, Type contextType, string edmName)
{
m_Logger = ServiceLocator.Current.GetInstance<ILoggerFacade>();
// Log invocation
m_Logger.Log("RepositoryBase constructor invoked.", Category.Info, Priority.None);
// Create object context
...
// Log completion
m_Logger.Log("RepositoryBase constructor completed.", Category.Info, Priority.None);
}
I am creating unit tests for my repository, and I have discovered that the ServiceLocator doesn't work, presumably because Prism isn't initialized for my test.
Can the ServiceLocator be used in a testing context? Sould I drop it and go back to injecting the IoC container directly? Since service locators seem to be falling out of favor generally, would I be better off not using it? Thanks for your help.
You need to create a mock IServiceLocator, initialize the service locator with your mock provider in your test.
That should do it.
I was able to unit test a Prism + Silverlight 4 application successfully and can't think of any reason why you shouldn't be able to use ServiceLocator from your unit tests. You will need to ensure that prism is initialized correctly in the [TestInitialize] part of your code though.
Related
Using Ninject, I have the following and wish to test using FluentAssertions:
[Test]
public void InterfacesEndingWithFactoryShouldBeBoundAsFactories() {
// Given
IKernel kernel = new StandardKernel();
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => !a.FullName.Contains("Tests")))
.SelectAllInterfaces()
.EndingWith("Factory")
.BindToFactory()
);
// When
var factory = kernel.Get<ICustomerManagementPresenterFactory>();
// Then
factory.Should().NotBeNull();
}
Is there any good ways to test whether the factories are actually bound properly?
I wrote an extension package for Fluent Assertions to test my Ninject bindings. Using it your test could be rewritten like this:
[Test]
public void InterfacesEndingWithFactoryShouldBeBoundAsFactories() {
// Given
IKernel kernel = new StandardKernel();
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => !a.FullName.Contains("Tests")))
.SelectAllInterfaces()
.EndingWith("Factory")
.BindToFactory()
);
// When
// Then
kernel.Should().Resolve<ICustomerManagementPresenterFactory>().WithSingleInstance()
}
As suggested by #Will Marcouiller, I would also extract the code to bootstrap the kernel into it's own class so it can be invoked in your app's composition root and in your unit tests.
First off, there is no ninject infrastructure to test which types are affected and which not. Unit testing is very complicated due to the fluent syntax and it's many interfaces which are returned when calling a method. So all you can practically do is integration testing.
Now, in my opinion, the From(...) is problematic. If you'd create a component where you could replace the assemblies you pass to From , create an extra test assembly containing a few types, and then test whether lets say interface IFoo is not bound, interface IFooFactory is bound, class Foo is not bound,.. you would have a functioning integration test.
Consider however, that if there is no binding for IFooFactory and SomeClass uses IFooFactory as constructor argument, ninject will throw an exception. Now if you have a composition root simply starting up the application will tell you whether the necessary bindings exist or not.
This test is even more useful than the factory convention integration test. Consider if someone accidentally bound the factory, manually, too. This won't show up with the convention-integration test, but starting the application, ninject will throw an exception stating that there are multiple bindings for this one interface.
In my program I have a situation that I can simplify to the following:
An IRepository of which I create a MemoryRepository and a SqlRepository implementation
A Mapper that gets the IRepository constructor injected.
A Mapper.Map() that contains business logic I want to test
I created a test where the Mapper receives the MemoryRepository.
By explicitly setting a property on the memory repository that will be used in the business logic I can now test this logic.
If I use injection however, I wouldn't have access to this repository anymore.
A bit of code tells you more then a 1000 normal words, here is the pastebin link.
How would you go about this?
If I understand your question correctly basically you are concerned that your repository was created AND injected when the test class was instantiated and so in your test method you cannot modify the state of your repository since it is already inside your mapper and, of course, your mapper should not expose the internals of the repository.
If that is the case then I don't think you have to worry, just modify the state of the myMemoryCategoryRepository and execute the mapper's method. Your mapper should behave accordingly because what you injected is a reference to the repository so the object inside the mapper is the same one as the one you would be modifying.
Dim myMemoryCategoryRepository As MemoryCategoryRepository = MemoryKernel.Instance.Get(Of MemoryCategoryRepository)()
Dim myCategoryMapper As CategoryMapper = New CategoryMapper(myMemoryCategoryRepository)
<TestMethod()> _
Public Sub GetCategoryStartDate_CategoryStartDateAndContractStartDate_ContractStartDateIsOldestDate()
myMemoryCategoryRepository.AnyFlag = True
myCategoryMapper.Execute()
Assert.AreEqual(expectedValue, myCategoryMapper.Value)
End Sub
Not entirely sure what you're asking here, are you testing the mapper or the repository? If you're testing the mapper, then fake the repository. You've already got the seams in place, either use a framework or create a fake repository manually in your tests that makes whatever happy noises you want for the sake of testing Mapper and create the mapper by passing in your fake into the constructor.
So by your own simplification,
Create a fake Repository inheriting from IRepository
Inject the fake into your Mapper that you are going to test
Test Mapper.Map()
If you need to verify some information on the Repository, use a Mock rather than a Stub.
Difference Between Mocks and Stubs
Short version of my questions:
Can anyone point me toward 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 help clarify for me how Controller-Repository
decoupling, mocking, and dependency injection work together?
Longer version of my questions:
What I'm trying to do ...
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 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.
What I've learned so far ...
I've spent some time working through some of this stuff, reading resources such as:
Implementing the Repository and Unit of Work Patterns in an
ASP.NET MVC Application
Building Testable ASP.NET MVC Applications
NerdDinner Step 12: Unit Testing
Using Repository and Unit of Work patterns with Entity Framework
4.0
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.
Where things got muddy for me ...
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:
Can anyone point me toward 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 help clarify for me how Controller-Repository
decoupling, mocking, and dependency injection work together?
EDIT:
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 :)
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.
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;
}
}
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.
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.
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");
}
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"]);
}
^ 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.
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.
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.
Here is the application that I'm creating. It is open source and available on github, and utilizes all of the required stuff - MVC3, NUnit, Moq, Ninject - https://github.com/alexanderbeletsky/trackyt.net/tree/master/src
Contoller-Repository decoupling is simple. All data operations are moved toward the Repository. Repository is an implementation of some IRepository type. The controller never creates repositories inside itself (with the new operator) but rather receives them either by constructor argument or property.
.
public class HomeController {
public HomeController (IUserRepository users) {
}
}
This technique is called "Inversion of Control." To support inversion of control you have to provide some "Dependency Injection" framework. Ninject is a good one. Inside Ninject you associate some particular interface with an implementation class:
Bind<IUserRepository>().To<UserRepository>();
You also substitute the default controller factory with your custom one. Inside the custom one you delegate the call to the Ninject kernel:
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 infrastructure is about to create a new controller, the call is delegated to the custom controller factory GetControllerInstance method, which delegates it to Ninject. Ninject sees that to create that controller the constructor has one argument of type IUserRepository. By using the declared binding, it sees that "I need to create a UserRepository to satisfy the IUserRepository need." It creates the instance and passes it to the constructor.
The constructor is never aware of what exact instance would be passed inside. It all depends on the binding you provide for that.
Code examples:
https://github.com/alexanderbeletsky/trackyt.net/blob/master/src/Web/Infrastructure/TrackyServices.cs https://github.com/alexanderbeletsky/trackyt.net/blob/master/src/Web/Infrastructure/TrackyControllerFactory.cs https://github.com/alexanderbeletsky/trackyt.net/blob/master/src/Web/Controllers/LoginController.cs
Check it out : DDD Melbourne video - New development workflow
The whole ASP.NET MVC 3 development process was very well presented.
The third party tools I like most are:
Using NuGet to install Ninject to enable DI throughout the MVC3
framework
Using NuGet to install nSubstite to create mocks to enable unit
testing
I'm having trouble using Moq in a UnitTesting project with Ninject.
First a few lines about my solution. It contains several projects (BussinesLogic, DAL, Infrastructure...). My goal is to UnitTest the logic i'm using in BussinessLogic project.
The solution is basicly for a windows service, but i've put in the logic so it can be run standalone. I'm using Ninject and i specify weather i want to use the ProductionModule or the TestingModule (windows service uses ProductionModule, console app uses TestingModule)
I'm using a factory pattern to get ninject kernel whenever i need it inside my application.
My TestingModule inherits from NinjectModule where i override the Load() method and there i do the binding. For instance:
Bind<IStorageManager>().To<StubStorageManager>();
I have the StubStorageManager but it's empty. It contains just the declaration of methods from IStorageManager.
The thing i would like to do is (in laymans terms):
Create a unitTest where i would create a new kernel specifying the TestingModule as it's parameter. Then i would like to create a mock object (let's say a mock of IStorageManager) storageManagerMock. Some method in IStorageManager returns a messageObject so i would probably need to mock that too, couse the bussiness logic is doing something based on that messageObject. So i would like to somehow set properties to that message object and then call some businessLogic method on it, so i can see if the logic works correctly.
I hope i didn't complicate it too much.
Please bear with me, i'm completely new to mocking and dependency injection, but am willing to learn.
I doubt you really want to be using Ninject in your tests. The whole point of using ninject is that you can decouple everything. You also want to try and keep everything decoupled from the dependency container itself if possible. Pass it in if you have to, or pass in factories that create the required object and have the container pass in the factory.
I suspect you probably want to do something like this:
public void ATest(){
//create a mock StorageManager
var managerMock = new Mock<IStorageManager>();
//create a mock MessageObject to be used by business logic
var messageObjectMock = new Mock<MessageObject>();
//have the storage manager return the mock message when required
managerMock.Setup(x => x.GetMessageObject()).Returns(messageObjectMock.Object);
//set up message expectations
messageObjectMock.Setup(x => x.ThisValueExpected).Returns(10);
messageObjectMock.Setup(x => x.ThisFunctionShouldBeCalled()).Verifiable("Function not called.");
//thing to test
BusinessLogicObject blo = new BusinessLogicObject(managerMock.Object);
blo.DoTheThingImTesting();
//make sure the business logic called the expected function, or do whatever check you need...
messageObjectMock.Verify();
}
I've created a unit test that tests interactions on my ViewModel class in a Silverlight application. To be able to do this test, I'm mocking the service interface, injected to the ViewModel. I'm using Moq framework to do the mocking.
to be able to verify bounded object in the ViewModel is converted properly, I've used a callback:
[Test]
public void SaveProposal_Will_Map_Proposal_To_WebService_Parameter()
{
var vm = CreateNewCampaignViewModel();
var proposal = CreateNewProposal(1, "New Proposal");
Services.Setup(x => x.SaveProposalAsync(It.IsAny<saveProposalParam>())).Callback((saveProposalParam p) =>
{
Assert.That(p.plainProposal, Is.Not.Null);
Assert.That(p.plainProposal.POrderItem.orderItemId, Is.EqualTo(1));
Assert.That(p.plainProposal.POrderItem.orderName, Is.EqualTo("New Proposal"));
});
proposal.State = ObjectStates.Added;
vm.CurrentProposal = proposal;
vm.Save();
}
It is working fine, but if you've noticed, using this mechanism the Assert and Act part of the unit test have switched their parts (Assert comes before Acting). Is there a better way to do this, while preserving correct AAA order?
I'm not sure that you've changed the semantics of the AAA order. Consider the execution of the test. Your mocked interface will not be called until the Action invokes it. Therefore, during execution, your program still follows the Arrange, Act, and Assert flow.
The alternative would be to use Data Injection and create an interface between your CampaignViewModel and the web service that it uses. You can then create a class in your UnitTests that saves your parameter information and Assert on that class member/property rather than use Moq to create a proxy on the fly.
Moq should not be used to simulate storage or assignment. Rather, use Moq to provide dummy mechanisms and values to allow your Unit Tests to execute. If Asserting storage is a requirement, then take the time to create a class that will hold on to your values.