- Home
- .NET tutorials
- How to write xUnit tests for dependency injection services
How to write xUnit tests for dependency injection services
Published: Monday 28 July 2025
How do you write xUnit tests for services that are used in dependency injection?
Mocking
One way to do is by mocking. Moq is a popular mocking framework for .NET. It allows you to create mock implementations of interfaces or classes. This is so you can test your code in isolation, without depending on actual implementations.
We want to unit test this CategoryService
class:
// ICategoryStorageService.cs
public interface ICategoryStorageService
{
List<CategoryTypeDto> Types { get; }
}
// ICategoryService.cs
public interface ICategoryService
{
CategoryTypeDto? GetCategoryType(int id);
}
// CategoryService.cs
public class CategoryService : ICategoryService
{
private readonly ICategoryStorageService _categoryComputersStorageService;
public CategoryService([FromKeyedServices("computers")]
ICategoryStorageService categoryComputersStorageService)
{
_categoryComputersStorageService = categoryComputersStorageService;
}
public CategoryTypeDto? GetCategoryType(int id) =>
_categoryComputersStorageService.Types.SingleOrDefault(s => s.Id == id);
}
Initialising the CategoryService
class involves providing an implementation for the ICategoryStorageService
type. We could create a new instance of that class that implements that interface. However, it might be coupled with other services meaning we would have to create instances for them as well. A better solution is to mock up an implementation of it.
To do that, we call the Mock
class and wrap the service around the generic type that it requires.
We can then pass the mock object into the constructor's parameters:
// CategoryServiceTests.cs
public class CategoryServiceTests
{
private readonly Mock<ICategoryStorageService> _categoryComputersStorageServiceMock;
private readonly CategoryService _categoryService;
public CategoryServiceTests()
{
_categoryComputersStorageServiceMock = new Mock<ICategoryStorageService>();
_categoryService = new CategoryService(_categoryComputersStorageServiceMock.Object);
}
}
Setting up mock returns
With the CategoryService
instance set up in the xUnit test class, we can unit test the GetCategoryType
method. This method relies on the Types
property from the ICategoryStorage
type.
We need to set up the Types
property to return an response. We are able to do that because the _categoryComputersStorageService
variable is a mock service.
In this example, we have set up the Types
property in the ICategoryStorageService
type to return an List<CategoryTypeDto>
instance. The first index returns an id of 2
and a name of Computers
, and the second returns an Id of 4
and a name of Software
.
When that property is called within the unit tests, it will return the mock return value specified in the tests, meaning that we know the preferred outcome.
In the GetCategoryType_WhenCalled_ReturnsResult
test, we pass in an Id
of 2
and 7
. We know that testing it with an Id
of 2
will return an object instance as we've mocked it in the Types
property in the ICategoryStorageService
type. We also know that passing in an Id
of 7
will return null
as we haven't specified that Id
within our Types
property.
// CategoryServiceTests.cs
public class CategoryServiceTests
{
private readonly Mock<ICategoryStorageService> _categoryComputersStorageServiceMock;
private readonly CategoryService _categoryService;
public CategoryServiceTests()
{
_categoryComputersStorageServiceMock = new Mock<ICategoryStorageService>();
_categoryService = new CategoryService(_categoryComputersStorageServiceMock.Object);
}
[Theory]
[InlineData(2)]
[InlineData(7)]
public void GetCategoryType_WhenCalled_ReturnsResult(int id)
{
// Arrange
_categoryComputersStorageServiceMock.Setup(s => s.Types)
.Returns(new List<CategoryTypeDto>
{
new(2, "Computers"),
new(4, "Software")
});
// Act
var act = _categoryService.GetCategoryType(id);
// Assert
if (id == 2)
{
Assert.Equivalent(act, new CategoryTypeDto(2, "Computers"));
}
else
{
Assert.Null(act);
}
}
}
Other tests
We can also do a similar thing for this web API controller:
// WebApiController.cs
[ApiController]
[Route("api/[controller]")]
public class WebApiController : ControllerBase
{
private readonly ICategoryService _categoryService;
private readonly ICategoryStorageService _categoryComputerStorageService;
public WebApiController(
ICategoryService categoryService,
[FromKeyedServices("computers")] ICategoryStorageService categoryComputerStorageService
)
{
_categoryService = categoryService;
_categoryComputerStorageService = categoryComputerStorageService;
}
[HttpGet("category-type")]
public IActionResult GetCategoryType()
{
return Ok(new
{
Category = _categoryService.GetCategoryType(2),
KeyedCategory = _categoryComputerStorageService.Types.SingleOrDefault(c => c.Id == 2)
});
}
}
Initialising the WebApiController
class involves providing an implementation for the ICategoryService
and ICategoryStorageService
types which we have created mock instances for. Within the unit test, we have set up the GetCategoryType
method with a parameter of 2
to return a particular CategoryTypeDto
instance. We've also done the same with the Types
property in the ICategoryStorageService
type.
When these methods are called within the unit tests, they will return the mock return values specified in the test and will therefore pass it:
// WebApiControllerTests.cs
public class WebApiControllerTests
{
private readonly Mock<ICategoryService> _categoryServiceMock;
private readonly Mock<ICategoryStorageService> _categoryComputerStorageServiceMock;
private readonly WebApiController _webApiController;
public WebApiControllerTests()
{
_categoryServiceMock = new Mock<ICategoryService>();
_categoryComputerStorageServiceMock = new Mock<ICategoryStorageService>();
_webApiController = new WebApiController(_categoryServiceMock.Object, _categoryComputerStorageServiceMock.Object);
}
[Fact]
public void GetCategoryType_WhenCalled_ReturnsResult()
{
// Arrange
_categoryServiceMock.Setup(s => s.GetCategoryType(2))
.Returns(new CategoryTypeDto(2, "Computers"));
_categoryComputerStorageServiceMock.Setup(s => s.Types)
.Returns(new List<CategoryTypeDto>
{
new(2, "Computers"),
new(4, "Software")
});
// Act
var act = _webApiController.GetCategoryType();
// Assert
Assert.IsType<OkObjectResult>(act);
Assert.Equivalent(((OkObjectResult)act).Value, new
{
Category = new CategoryTypeDto(2, "Computers"),
KeyedCategory = new CategoryTypeDto(2, "Computers")
});
}
}
Testing real instances
If you are looking to add integration tests, you may wish to test real instances of the services that are injected as part of dependency injection.
To do that, you can create your own service collection, add the services and then build the service provider. You can then use that service provider instance to resolve any instances by calling either the GetService
, GetRequiredService
, GetKeyedService
or GetRequiredKeyedService
methods.
// WebApiControllerRealTests.cs
public class WebApiControllerRealTests
{
private readonly WebApiController _webApiController;
public WebApiControllerRealTests()
{
var services = new ServiceCollection();
services.AddScoped<ICategoryService, CategoryService>();
services.AddKeyedSingleton<ICategoryStorageService, CategoryComputersStorageService>("computers");
var serviceProvider = services.BuildServiceProvider();
var categoryService = new CategoryService(
serviceProvider.GetRequiredKeyedService<ICategoryStorageService>("computers")
);
var categoryComputerStorageService = new CategoryComputersStorageService();
_webApiController = new WebApiController(categoryService, categoryComputerStorageService);
}
[Fact]
public void GetCategoryType_WhenCalled_ReturnsResult()
{
// Act
var act = _webApiController.GetCategoryType();
// Assert
Assert.IsType<OkObjectResult>(act);
Assert.Equivalent(((OkObjectResult)act).Value, new
{
Category = new CategoryTypeDto(2, "Computers"),
KeyedCategory = new CategoryTypeDto(2, "Computers")
});
}
}
Because of this, you don't have to do any setup within the class members as you are not mocking any services. However, be mindful that you'll need to create new instances for each of the classes that are dependent on each other. This could become complex if you have many services. You may also come into issues if they rely on external sources such as a database.
Watch the video
Watch the video where we show you how to write these xUnit tests. We also show you how to create an xUnit test project and how to run them:
And if you want to run these xUnit tests for yourself, you can download the code example.
Latest tutorials

