I'm very new to testing and IoC containers and have two projects:
MySite.Website (MVC)
MySite.WebsiteTest
Currently I have an IoC container in my website. Should I recreate another IoC container for my test? Or is there a way to use the IoC in both?
When you have an IoC container, hopefully you will also have some sort of dependency injection going on - whether through constructor or setter injection.
The point of a unit test is to test components in isolation and doing DI goes a long way in aiding that. What you want to do is unit test each class by manually constructing it and passing it the required dependencies, not rely on container to construct it.
The point of doing that is simple. You want to isolate the SUT(System Under Test) as much as possible. If your SUT relies on another class and IoC to inject it, you are really testing three systems, not one.
Take the following example:
public class ApiController : ControllerBase {
IRequestParser m_Parser;
public ApiController(IRequestParser parser) {
m_Parser = parser;
}
public ActionResult Posts(string request) {
var postId = m_Parser.GetPostId(request);
}
}
The ApiController constructor is a dependency constructor and will get invoked by IoC container at runtime. During test, however, you want to mock IRequestParser interface and construct the controller manually.
[Test]
public void PostsShouldCallGetPostId() {
//use nmock for mocking
var requestParser = m_Mocks.NewMock<IRequestParser>();
//Set up an expectation that Posts action calls GetPostId on IRequestParser
Expect.Once.On(requestParser).Method("GetPostId").With("posts/12").Will(Return.Value(0));
var controller = new ApiController(requestParser);
controller.Posts("posts/12");
}
Testing is about real implementation. So you normally should not use IOC in your unit tests. In case you really feel needing it (one component depending on another one), using an interface to isolate the interaction and using a mocking lib (Moq is good) to mock it and do the testing.
The only chance I see IOC container is necessary for testing is in integration testing.
Related
I am not sure if what i am doing is actually the "correct" way of doing unit tests with DI. Right now i ask my ViewModelLocator to actually create all the instances i need, and just get the instance i need to test, which makes it very simple to test a single instance because lets asume that Receipt needs a Reseller object to be created, reseller needs a User object to be created, user need some other object to be created, which creates a chain of objects to create just to test one single instance.
With di usally interfaces will get mocked and parsed to the object which you would like to create, but how about simple Entities/ViewModels?
Whats the best practice to do unit testing with DI involved?
public class JournalTest
{
private ReceiptViewModel receipt;
private ViewModelLocator locator;
[SetUp]
public void SetUp()
{
locator = new ViewModelLocator();
receipt = SimpleIoc.Default.GetInstance<ReceiptViewModel>();
}
[TearDown]
[Test]
public void CheckAndCreateNewJournal_Should_Always_Create_New_Journal()
{
receipt.Sale.Journal = null;
receipt.Sale.CheckAndCreateNewJournal();
Assert.NotNull(receipt.Sale.Journal);
}
}
First, you aren't using Dependency Injection in your code. What you have there is called Service Locator (Service Locators create a tight coupling to the IoC/Service Locator and makes it hard to test).
And yes, it's bad (both Service Locator and Dependency Injection), because it means: You are not doing a UnitTest, you are doing an integration Test.
In your case the ReceiptViewModel will not be tested alone, but your test also tests the dependencies of ReceiptViewModel (i.e. Repository, Services injected etc.). This is called an integration test.
A UnitTest has to test only the class in question and no dependencies. You can achieve this either by stubs (dummy implementation of your dependencies, assuming you have used interfaces as dependencies) or using mocks (with a Mock framework like Moq).
Which is easier/better as you don't have to implement the whole class, but just have to setup mocks for the methods you know that will be required for your test case.
As an additional note, entities you'll got to create yourself. Depending on your UnitTest framework, there may be data driven tests (via Attributes on the test method) or you just create them in code, or if you have models/entities used in many classes, create a helper method for it.
View Models shouldn't be injected into constructor (at least avoided), as it couples them tightly
Units tests should run quickly and should be deterministic. That means you have to mock/stub everything that brokes these two rules.
The best way to mock/stub dependancies is to inject them. In the production, classes are assembled by DI framework, but in unit tests you should assemble them manually and inject mocks where needed.
There is also a classic unit test approach where you stub/mock every dependency of your class, but it's useless since you don't gain anything by that.
Martin Fowler wrote great article about that: link
You should also read Growing Object-oriented software: Guided by tests. Ton of useful knowledge.
I need to MOQ wcfClientService while calling the SomeMethod().
Class ABC : IABC
{
internal WcfClientService wcfClientService = new WcfClientService();
public void SomeMethod(object pqr)
{
using(wcfClientService)
{
wcfClientService.Save(some parameters)
}
}
}
With the current implementation, you cannot isolate the "ABC" class as it is tightly coupled with wcfClientService. I would strongly suggest things mentioned below:
Extract an interface IClientService. This makes your "ABC" class depend on an abstraction instead of a concrete implementation. It will help in short term to isolate "ABC" better for unit testing. In long term, your "ABC" class would not have to be changed if a "RestfulClientService" was to be used.
Consider introducing a Dependency Injection framework. Anything like a Spring.Net, Unity or Autofac should serve the purpose. Ideally, your production code should never instantiate a dependency. Let the framework take care of it.
Now, register and resolve a mock implementation of the interface using the DI framework and start unit testing the "ABC" class.
I have a very simple package structure, only one level deep for all my grails artifacts- the name of the application "estra"- because the grails application structure is already providing the separation folders. But when writing unit-tests all the classes are inside the same estra.* package and I want to keep them separated like this estra.domain, estra.controllers, etc.
Right now everything works fine, but the tests are pretty simple. Will I face any problem in the future with dependency injection or something?
No, the package name don't influence in your test since in your test class you "say" which class is tested, using the #TestFor annotation. But remember that in unit tests you need to manually set your dependencies.
class ServiceOne {
def serviceTwo
}
#TestFor(ServiceOne)
class ServiceOneTests {
#Before
public void setup() {
service.serviceTwo = new ServiceTwo() //or mocked instance...
}
}
I want to use Unity as an IoC besides the UnitOfWork and Repository patterns. I read various related articles and questions but none of them satisfied me completely.
I have a problem with all approaches. An example would explain better my problem:
We want to work with two repositories at two separate classes (maybe the business services) but the overall works are in a unit.
Start point is the LocalService1.Method1 method.
public class LocalService1
{
public void Method1(int id)
{
var repository1 = Container.Current.Resolve<IRepository1>(); // Injects the IUnitOfWork for the repository.
var entity1 = repository1.GetEntity1(id);
var service2 = Container.Current.Resolve<LocalService2>(); // Maybe it’s better not to use IoC for business logic. This is not my issue.
service2.Method2(entity1)
}
}
...
public class LocalService2
{
public void Method2(Entity1 entity1)
{
var repository2 = Container.Current.Resolve<IRepository2>(); // Injects the IUnitOfWork for the repository.
var count = repository2.GetEntity2sCount(entity1.Id);
// Do some works with count and entity1
}
}
The main question is that “How can I share the UnitOfWork (here can be ObjectContext) between the IRepository1 and IRepsitory2 while calling the LocalService1.Method1?”.
More important thing is that “I want to be sure about UnitOfWork disposal”.
I guess the answers would focus on these issues:
IoC configuration
Life Time configuration
Disposal time (How and when?)
If you recommend using “HttpContext” please consider about non-web environments.
I know my question is almost about the “Life time management” but I’m looking for an exhaustive approach.
First: Don't use Unity as a ServiceLocator. This is considered an anti-pattern. Use constructor injection instead.
Unity's LifetimeManagers don't clean up after themselves. This feature is on the wish list for Unity vNext.
If you want your objects to be disposed you should create your own LifetimeManager and a related BuilderStrategy that do clean up.
There is a sample in the TecX project (inside TecX.Unity.Lifetime) which is taken from Mark Seemann's book Dependency Injection in .NET.
I'm using Ninject in an MVC project and I've used the autoregistration features in Ninject.Mvc and have my bindings set up in my application class. However, I have a place where I want to create an instance separate from those bindings. In StructureMap, you can do var foo = ObjectFactory.GetInstance<IFoo>(); and it will resolve it for you. Is there an equivalent in Ninject 2? I can't seem to find it anywhere.
AFAIK, NInject doesn't have static method like this so all resolving should go to some kernel.
But you can implement it easily;
class ObjectFactory
{
static IKernel kernel = new StandardKernel(.....);
public static T GetInstance<T>()
{
return kernel.Get<T>();
}
}
Although, IMO, NInject is much more useful as DI container than as service locator.
You can also use Common Service Locator as an abstraction layer for Ninject IOC which offers what you want. The advantage is that you can later switch container if it does not fit your needs anymore.
In your code you can use something like this:
ServiceLocator.Current.GetInstance<Type>();