13

Unit Testing .NET 5 Console Applications with Dependency Injection

 2 years ago
source link: https://www.programmingwithwolfgang.com/unit-testing-net-5-console-applications/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
3 hours ago2021-09-13T00:00:00+02:00 by Wolfgang Ofner

In my last post, I created a .NET 5 console application and configured dependency injection. This was pretty straight-forward and only needed a couple of lines of code.

Today, I will show you how to create unit tests when using dependency injection in a .NET 5 (or .NET Core) console application.

Create Unit Tests using xUnit

You can find the code of the demo on Github.

Create a new .NET 5 test project using xUnit and create a reference to the main project. You can use any unit testing and faking framework you like. For this demo, I am using xUnit and Moq. Additionally, I am using FluentAssertions to make the assertions more readable.

Implementing unit tests for a .NET 5 console application with dependency injection is the same as for any other project. The only minor difficulty is how to test the following method which creates an instance of IGreeter and then calls the Greet() method on it.

public static string GreetWithDependencyInjection(IServiceProvider services) { using var serviceScope = services.CreateScope(); var provider = serviceScope.ServiceProvider;

var greeter = provider.GetRequiredService<IGreeter>();

return greeter.Greet(); }

The difficulty when testing this method is the IServiceProvider which has to be configured to be able to create an instance of the IGreeter interface.

Create a fake Service Provider

The solution to the problem is to create a fake IServiceProvider and IServiceScope object. The IServiceProvider fake then can be configured to return a fake IServiceScopeFactory object. This fake object can be used as the IServiceProvider parameter of the GreetWithDependencyInjection() method. The full code looks as follows:

namespace ConsoleDependencyInjection.Test { public class ProgramTests { private readonly IServiceProvider _serviceProvider;

public ProgramTests() { var serviceProvider = new Mock<IServiceProvider>(); serviceProvider.Setup(x => x.GetService(typeof(IGreeter))).Returns(new ConsoleGreeter(Mock.Of<IFooService>()));

var serviceScope = new Mock<IServiceScope>(); serviceScope.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object);

var serviceScopeFactory = new Mock<IServiceScopeFactory>(); serviceScopeFactory.Setup(x => x.CreateScope()).Returns(serviceScope.Object);

serviceProvider.Setup(x => x.GetService(typeof(IServiceScopeFactory))).Returns(serviceScopeFactory.Object);

_serviceProvider = serviceProvider.Object; }

[Fact] public void GreetWithDependencyInjection_ShouldReturnGreetingMessage() { var result = Program.GreetWithDependencyInjection(_serviceProvider);

result.Should().Be("Hello World from the Console Greeter"); } } }

The code in the constructor might look complicated but if you start a new project, all you have to do is to copy it into the new project and you are good to go.

Test Classes without the IServiceProvider Interface

As previously mentioned, every other class besides the Program.cs can be tested as you are used to. For example, testing the ConsoleGreeter is straight-forward. Create a new object of the ConsoleGreeter, add a fake interface in the constructor and then call the method you want to test. The method should return the value you expect.

namespace ConsoleDependencyInjection.Test { public class ConsoleGreeterTests { private readonly ConsoleGreeter _testee;

public ConsoleGreeterTests() { _testee = new ConsoleGreeter(Mock.Of<IFooService>()); }

[Fact] public void Greet_ShouldReturnGreetingMessage() { var result = _testee.Greet();

result.Should().Be("Hello World from the Console Greeter"); } } }

Testing the Unit Tests

Run all the unit tests and you should see both running successfully.

The Tests ran successfully

Conclusion

Creating unit tests for a .NET 5 console application that uses dependency injection only takes a couple of lines of code to configure the service provider. This code can be copied to any new project, making it even easier to set up.

You can find the code of the demo on Github.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK