Answered by:
How to get a service from anywhere using Microsoft.DependencyInjection?

Question
-
User911375783 posted
Hello,
I'm working on an ASP.NET Core 3.1 Web API project and I'm writing some integration tests. I created a database fixture that I use in my tests and for that I wanted to grab an IOptions object from the dependency injection container, but I don't know how to do that or even if it's possible.
Since I don't know how to use the dependency injection container, I wrote my fixture like:
public MongoDbFixture() {
// This is already configured in Startup as a singleton
// but I don't know how to get the IOptions object here. To avoid all the following: var config = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .AddJsonFile("appsettings.Testing.json").Build(); var section = config.GetSection(nameof(RetroactiuneDbSettings)); _settings = new RetroactiuneDbSettings(); _settings.ConnectionString = section.GetValue<string>("ConnectionString"); _settings.TokensCollectionName = section.GetValue<string>("TokensCollectionName"); _settings.FeedbackCollectionName = section.GetValue<string>("FeedbackCollectionName"); _settings.FeedbackReceiverCollectionName = section.GetValue<string>("FeedbackReceiverCollectionName"); _settings.DatabaseName = section.GetValue<string>("DatabaseName"); var client = new MongoClient(_settings.ConnectionString); Database = client.GetDatabase(_settings.DatabaseName); }And my test, using xUnit 2.4 looks like:
public class TestFeedbackReceiver : IClassFixture<WebApiTestingFactory>, IClassFixture<MongoDbFixture> { private readonly MongoDbFixture _mongoDb; private readonly HttpClient _client; public TestFeedbackReceiver(WebApiTestingFactory factory, MongoDbFixture mongoDbFixture) { _client = factory.CreateClient(); _mongoDb = mongoDbFixture; } [Theory, AutoData] public async Task Test_CreateFeedbackReceiver_Ok(IEnumerable<FeedbackReceiverDto> items) { // Arrange await _mongoDb.DropAsync(); var feedbackReceiversDto = items.ToList(); var jsonContent = JsonSerializer.Serialize(feedbackReceiversDto); // Test var httpResponse = await _client.PostAsync("/api/v1/FeedbackReceiver/", new StringContent(jsonContent, Encoding.UTF8, "application/json")); // Assert httpResponse.EnsureSuccessStatusCode(); var filter = new FilterDefinitionBuilder<FeedbackReceiver>().Empty; var createdDocs = await _mongoDb.FeedbackReceiverCollection.CountDocumentsAsync(filter); Assert.Equal(feedbackReceiversDto.Count(), createdDocs); } }
Is there a way I can retrieve an IOptions or another service from the dependency injection container which is used by my web application that is currently being tested?
Thank you!
Sunday, May 30, 2021 4:20 PM
Answers
-
User-474980206 posted
As a fixture is xunit’s version of DI, you can not use .net core services instead for fixtures in tests. I believe there been requests for injecting fixtures in fixtures. If just want IOptions in tests, crate a fixture that returned an IOptions handler.
Also you could create a fixture that created services containers to use.
https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection
Note: while you can add services di support, your code will need to use when creating class instances, xunit will not do it for you.
- Marked as answer by An0nym0u5User Tuesday, June 22, 2021 12:00 AM
Sunday, May 30, 2021 5:15 PM
All replies
-
User-474980206 posted
As a fixture is xunit’s version of DI, you can not use .net core services instead for fixtures in tests. I believe there been requests for injecting fixtures in fixtures. If just want IOptions in tests, crate a fixture that returned an IOptions handler.
Also you could create a fixture that created services containers to use.
https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection
Note: while you can add services di support, your code will need to use when creating class instances, xunit will not do it for you.
- Marked as answer by An0nym0u5User Tuesday, June 22, 2021 12:00 AM
Sunday, May 30, 2021 5:15 PM -
User911375783 posted
Thank you for clarifying!
I've experimented a bit with the code, and I can use a simple class instead of a xunit fixture and give it the service/IOptions as a dependency
public class TestFeedbackReceiver : IClassFixture<WebApiTestingFactory>
{
private readonly MongoDbFixture _mongoDb;
private readonly HttpClient _client;
public TestFeedbackReceiver(WebApiTestingFactory factory)
{
_client = factory.CreateClient();
var dbSettings = factory.Services.GetRequiredService(typeof(IOptions<RetroactiuneDbSettings>));
_mongoDb = new MongoDbFixture((IOptions<RetroactiuneDbSettings>) dbSettings);
}
}Sunday, May 30, 2021 5:30 PM