DEV Community

Jimmy
Jimmy

Posted on

2 1

Simplify arranging of dependencies in tests

I have created a NuGet package to simplify the arrange step when writing tests, that's useful when you use dependency injection.

Basic use

nuget install ArrangeDependencies.Autofac

var arrange = Arrange.Dependencies(dependencies =>
{
    dependencies.UseImplementation<IUserService, UserService>();
});

var userService = arrange.Resolve<IUserService>();

// Act

// Assert

This will produce a UserService to start testing on. All the injected dependencies in UserService will be injected as Mock.Of<T>(), resulting in methods calls on any dependency will return the default value of the return type.

When adding more dependencies to the UserService you do not need to change all the tests setups that you have already created. You may, however, still need to change some tests if the behavior has changed.

This arrange block can be simplified by a one liner

var arrange = Arrange.Dependencies<IUserService, UserService>();

This setup will call on UseImplementation<IUserService, UserService>() under the hood.

Use Mock

nuget install ArrangeDependencies.Autofac

var arrange = Arrange.Dependencies<IUserService, UserService>(dependencies =>
{
    dependencies.UseMock<IUserRepository>(mock => {
        mock.Setup(x => x.GetByName(It.IsAny<string>())).Returns(new Basis.Entites.User());
    });
});

Now UserService will use your mocked IUserRepository, instead of the default Mock.Of<T>(), and return a new User when GetByName(name) is called. The mock action is like any other Mock setup that you probably already is used to.

Use DbContext

nuget install ArrangeDependencies.Autofac.EntityFrameworkCore

var arrange = Arrange.Dependencies(dependencies =>
{
    dependencies.UseDbContext<TestDbContext>();
});

This will setup an in memory database for TestDbContext in your test.

Use Entity

nuget install ArrangeDependencies.Autofac.EntityFrameworkCore

var arrange = Arrange.Dependencies(dependencies =>
{
    dependencies.UseEntity<User, TestDbContext>((user) => user.SetName("Test name"));
});

This will add a new user into TestDbContext that can be used in testing. NOTE: UseDbContext is called under the hood here, so you don't need to define it.

var arrange = Arrange.Dependencies(dependencies =>
{
    dependencies.UseEntity<Company, TestDbContext>((company) => company.SetName("Test name"), out var company);
    dependencies.UseEntity<User, TestDbContext>((user) => {
        user.SetName("Test name");
        user.SetCompany(company);
    });
});

You can also couple the entites by using the out parameter.

Use MemoryCache

nuget install ArrangeDependencies.Autofac.MemoryCache

var user = "Cache test user"

var arrange = Arrange.Dependencies<IUserService, UserService>(dependencies =>
{
    dependencies.UseMemoryCache("Cache test", user);
});

With this you can test your cache, where the first parameter is the key and the second is the cached object.

Use Logger

nuget install ArrangeDependencies.Autofac.Logger

Mock<ILogger<LoggingService>> logger = null;

var arrange = Arrange.Dependencies<ILoggingService, LoggingService>(dependencies =>
{
    dependencies.UseLogger(out logger);
});

var loggingService = arrange.Resolve<ILoggingService>();
loggingService.LogError();

logger.Verify(LogLevel.Error, Times.Once());

With this you can verfy that you log errors (or any other Log Level).

Create your own extensions

This library is extensible by nature, so if you find yourself writing the same mock setup over and over again, I suggest you to create your own extension method for that mock.

public static class UseMyCustomExtensionExtension
{
    public static IArrangeBuilder<ContainerBuilder> UseMyCustomExtension(this IArrangeBuilder<ContainerBuilder> arrangeBuilder, /* parameters... */)
    {
        if(arrangeBuilder is ArrangeBuilder builder)        
            builder.UseMock<IMyCustomExtension>(mock => /* setup mock here */);

        return arrangeBuilder;
    }
}

Top comments (0)

Feature flag article image

Create a feature flag in your IDE in 5 minutes with LaunchDarkly’s MCP server 🏁

How to create, evaluate, and modify flags from within your IDE or AI client using natural language with LaunchDarkly's new MCP server. Follow along with this tutorial for step by step instructions.

Read full post

👋 Kindness is contagious

Take a moment to explore this thoughtful article, beloved by the supportive DEV Community. Coders of every background are invited to share and elevate our collective know-how.

A heartfelt "thank you" can brighten someone's day—leave your appreciation below!

On DEV, sharing knowledge smooths our journey and tightens our community bonds. Enjoyed this? A quick thank you to the author is hugely appreciated.

Okay