c# - Understanding why we use Inversion of control containers for unit testing - TagMerge
5Understanding why we use Inversion of control containers for unit testingUnderstanding why we use Inversion of control containers for unit testing

Understanding why we use Inversion of control containers for unit testing

Asked 1 years ago
6
5 answers

Why would you want to use a DI framework in your tests? Are your object graphs that difficult to compose?

Personally I think you would be better just making the tests create their dependencies explicitly as then injecting mocks or stubs will be explicit in the tests and very visible.

It also hides any issues around creating complex dependency hierarchies. Creating all the objects in the tests means you would have to feel the pain of creating those dependencies and might motivate you to improve the design.

I don't think that using a DI framework buys you anything in this situation, other than obfuscating the dependencies that your test has.

Integration tests might be a different story, but for unit tests...

Source: link

0

Auto-mocking container can solve this exact issue. It will automatically stub/setup incoming dependencies with mocking framework of your choice, leaving to maintain less code and focus more on tests.

For following dependency:

public class SystemUnderTest
{
    public SystemUnderTest(IMockA mockA, IMockB mockB, IMockC mockC, IMockD mockD)
    {
    }

    public int Exercise()
    {
    }
}

instead of doing this:

[Fact]
public void Test()
{
    var sut = new SystemUnderTest(
        Mock.Of<MockA>(Mock.Of<UnknownA>(Mock.Of<UnknownB>(), Mock.Of<UnknownC>())),
        Mock.Of<MockB>(Mock.Of<UnknownC>()),
        Mock.Of<MockC>(Mock.Of<UnknownD>(), Mock.Of<UnknownE>()),
        Mock.Of<MockD>(Mock.Of<UnknownD>())
    );
}

it can shortened to:

[Fact]
public void Test()
{
    var sut = Container.Resolve<SystemUnderTest>();
    var mockA = Container.Resolve<Mock<MockA>>().Setup(...);
    var mockB = Container.Resolve<Mock<MockB>>().Setup(...);
}

Full disclosure: I've made a simple auto-mocking container library Tethos which these listed example are from.

It supports all popular mocking frameworks Moq, NSubstitute and FakeItEasy.

Source: link

0

For DI example, say your application has a text-editor component, and you want to provide spell checking. Your standard code would look something like this:
public class TextEditor {

    private SpellChecker checker;

    public TextEditor() {
        this.checker = new SpellChecker();
    }
}
What we've done here creates a dependency between the TextEditor and the SpellChecker. In an IoC scenario we would instead do something like this:
public class TextEditor {

    private IocSpellChecker checker;

    public TextEditor(IocSpellChecker checker) {
        this.checker = checker;
    }
}
In the second code example we are creating an abstraction by having the SpellChecker dependency class in TextEditor's constructor signature (not initializing dependency in class). This allows us to call the dependency then pass it to the TextEditor class like so:
SpellChecker sc = new SpellChecker(); // dependency
TextEditor textEditor = new TextEditor(sc);
For example, in an old school menu, you might have:
print "enter your name"
read name
print "enter your address"
read address
etc...
store in database
In a GUI program or somesuch, instead we say:
when the user types in field a, store it in NAME
when the user types in field b, store it in ADDRESS
when the user clicks the save button, call StoreInDatabase

Source: link

0

Most frameworks such as .NET or Enterprise Java display this pattern:
public class ServerFacade {
    public <K, V> V respondToRequest(K request) {
        if (businessLayer.validateRequest(request)) {
            Data data = DAO.getData(request);
            return Aspect.convertData(data);
        }
        return null;
    }
}
Although all these assumptions might be valid at some time, they couple the implementation of the ServerFacade to the DAO implementation. Designing the application in the manner of inversion of control would hand over the control completely to the DAO object. The code would then become
public class ServerFacade {
    public <K, V> V respondToRequest(K request, DAO dao) {
        return dao.getData(request);
    }
}

Source: link

0

Below is an example of a class that is directly coupled to a dependency...
public class MyClass
{
    public void MyMethod()
    {
        var logger = new FileSystemLogger("LogFile.txt");

        logger.WriteLog("Hello!");
    }
}
Now if this was rewritten so that rather than depending on the FileSystemLogger, it instead depends on an abstraction...
public class MyClass
{
    public void MyMethod(ILogger logger)
    {
        logger.WriteLog("Hello!");
    }
}
Let's start with an example of binding interfaces. This would normally go in your application startup / bootstrap code ...
var builder = new ContainerBuilder();
builder.RegisterType<FileSystemLogger>().As<ILogger>();
var container = builder.Build();
If you're dealing with an ASP.NET MVC application, then you just need to register your IoC Container with ASP.NET, and it'll do the rest for you (different IoC Containers do this in different ways, so consult their documentation for details). You can then just request the interfaces in your Controllers by adding constructor parameters ...
public class MyController : Controller
{
    private readonly ILogger _logger;

    public MyController(ILogger logger)
    {
        _logger = logger;
    }
}
If you're not working with MVC, but say just a normal console application, then you'll have to explicitly resolve at least one instance manually...
var logger = container.Resolve<ILogger>();

Source: link

Recent Questions on c#

    Programming Languages