locked
How to get a service from anywhere using Microsoft.DependencyInjection? RRS feed

  • 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 Anonymous Thursday, October 7, 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 Anonymous Thursday, October 7, 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