I am using Autofac in my project,but i am unable to do a unit test on one particular class.
Consider the following Scenario :
//Class to be tested
public Class A
{
private SomeAutoFacClass B;
public void DoSomething()
{
B = scope.Resolve<ClassName>();// Resolve the object needed
// Do something with instance B
}
}
// Test class
public Class ATest
{
private A a;
[test]
public void TestMethod()
{
a.DoSomething();//*This method causes a null reference exception as it tries to resolve the objects*
}
}
In the code above,i am not able to unit test case due to the dependency injection which is only specific to that particular class. how do i solve this? I also tried creating a autofaccontainer using Moq. But that too fails.
The reason you are not able to test your class is because your class takes a dependency on your DI Container. This is an implementation of the Service Locator anti-pattern. It's an anti-pattern because:
the problem with Service Locator is that it hides a class' dependencies, causing run-time errors instead of compile-time errors, as well as making the code more difficult to maintain because it becomes unclear when you would be introducing a breaking change.
Instead, design your classes around
Components are built-up by your DI Container and are registered in your Composition Root, while data-centric objects are new
ed up in code outside the Composition Root. In that case you need to pass along a dependency to an already constructed object.
In case you build and test a component, your code would typically look as follows:
public class ComponentA
{
private ClassName b;
public ComponentA(ClassName b)
{
this.b = b;
}
public void DoSomething()
{
// Do something with instance B
}
}
// Test class
public Class ATest
{
[test]
public void TestMethod()
{
// Arrange
B b = new FakeB();
var a = new ComponentA(b);
// Act
a.DoSomething();
// Assert
// Check whether be was invoked correctly.
}
}
In case you build and test a data-centric object that requires a dependency for one of its operations, your code would typically look as follows:
public class EntityA
{
public string Name { get; set; }
public int Age { get; set; }
public void DoSomething(ClassName b)
{
// Do something with instance B
}
}
// Test class
public Class ATest
{
[test]
public void TestMethod()
{
// Arrange
B b = new FakeB();
var a = new EntityA { Name = "Bert", Age = 56 };
// Act
a.DoSomething(b);
// Assert
// Check whether be was invoked correctly.
}
}
So to answer your initial question:
How do i unit test a class that uses IoC container classes
You don't. Your application code should not depend on the DI Container, because that leads to all kinds of complications such as being hard to test.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With