This is a dilemma. Say we have two classes
Class A
{
public int memberValue;
}
interface IB
{
int fun();
}
Class B : IB
{
public int fun()
{
var a = new A();
switch(a.memberValue)
{
case 1:
//do something
break;
case 2:
//do something
break;
}
}
}
Now this presents two tightly coupled classes. For testing B.fun(), we need to mock Class A and provide multiple values for A.memberValue.
As the A object is not required anywhere else beyond the scope of B.fun(), I dont see why should we inject it through B's constructor. How can we unit test this method fun() ?
Firstly you should probably create an interface for A
as well, but if this is just a simple POCO data class, it might be better to just make its properties virtual
instead to allow for mocking. You have 3 options I think:
Inject A to the constructor of B
if it is a class that will be used often (e.g. a logging class or something). Then you can create a mock version in your test to check how A
is used (remember, mocking is for testing behaviour with dependencies).
public class A : IA { ... }
public class B : IB
{
private readonly A a;
public B(IA a)
{
this.a = a;
}
public void Func()
{
//... use this.a ...
}
}
[Test]
public void Func_AHasValue1_DoesAction1()
{
Mock<IA> mock = new Mock<IA>();
mock.Setup(a => a.somevalue).Returns("something");
B sut = new B(mock.Object);
sut.Func();
mock.Verify(m => m.SomethingHappenedToMe());
}
A
to the method if it is something that B
needs to work with (as it seems here). You can still create a mock version for use in your tests. This is the same code as the above, but mock
is passed to the method instead of the constructor. This is the better method if A
is some data class generated at runtime instead of a class with behaviour.Create a factory class for A
and inject that into the constructor. Change the method to get A
instances from the factory and inject a mock factory in your tests to verify the behaviour.
public class AFactory : IAFactory
{
public IA Create() { ... }
}
public class B : IB
{
private readonly IAfactory factory;
public B(IAFactory factory)
{
this.factory = factory;
}
public void Func()
{
IA a = factory.Create();
//... use this.a ...
}
}
[Test]
public void Func_AHasValue1_DoesAction1()
{
Mock<IAFactory> mockFactory = new Mock<IAFactory>();
Mock<IA> mock = new Mock<IA>();
mockFactory.Setup(f => f.Create()).Returns(mock.Object);
mock.Setup(a => a.somevalue).Returns("something");
B sut = new B(mockFactory.Object);
sut.Func();
mock.Verify(m => m.SomethingHappenedToMe());
}
A
is something that does have behaviour but can't be created without something generated at runtime. You'll have to look at your application to see which is most applicable.