8

I nuget the xunit.DependencyInjection package and created my construction with my interfaces. The test case compiles but when I run xunits it does not execute my constructor dependency injection.

 public class TestSuite{
  IARepository _aRepository;
  IBRepository _bRepository;
    public TestSuite(IARepository aRepository, IBRepository bRepository)
    {
        _aRepository = aRepository;
        _bRepository = bRepository;
    }
}

The GitHub suggests that constructor injection is possible: https://github.com/pengweiqhca/Xunit.DependencyInjection/tree/master/Xunit.DependencyInjection.Test

Startup.cs

 public class Startup
 {
    public void ConfigureServices(IServiceCollection services)
    {

    var configuration = new ConfigurationBuilder()
            .SetBasePath(System.IO.Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", false, true)
            .Build();

                    
        var connectionString =     configuration.GetConnectionString("A_DbCoreConnectionString");
        services.AddDbContext<AContext>(options1 => options1.UseSqlServer(connectionString));

        connectionString= configuration.GetConnectionString("B_DbCoreConnectionString");
        services.AddDbContext<BContext>(options2 => options2.UseSqlServer(connectionString));

        services.AddTransient<IARepository, ARepository>();
        services.AddTransient<IBRepository, BRepository>();
    }
  }

A and B Repository.cs

public class ARepository :IARepository
{
    public AContext _dbContext; 
    public ARepository(AContext dbContext) 
    {
        _dbContext = dbContext;
    }
    ...
}

public class BRepository :IBRepository
{
    public BContext _dbContext; 
    public BRepository(BContext dbContext) 
    {
        _dbContext = dbContext;
    }
    ...
}
Golden Lion
  • 3,840
  • 2
  • 26
  • 35
  • You have a Startup class with a ConfigureServices method where you add your implementations for those interfaces? – rene Aug 05 '20 at 16:31
  • System.AggregateException : One or more errors occurred. (Can't load type TestWebApi.Startup in 'TestWebApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null') (A test class may only define a single public constructor.) ---- System.InvalidOperationException : Can't load type TestWebApi.Startup in 'TestEsiWebApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' ---- A test class may only define a single public constructor. – Golden Lion Aug 05 '20 at 16:40
  • Can you [edit] your question to include the code that produces that exception. The [mcve] page might be helpful with that – rene Aug 05 '20 at 16:46
  • Adding a startup file – Golden Lion Aug 05 '20 at 16:51
  • 1
    so you don't have a `Startup` class? – rene Aug 05 '20 at 16:56
  • It needs the entity framework context added but the constructor for startup does not allow for any parameters. I need IConfiguration configuration – Golden Lion Aug 05 '20 at 17:16
  • I need IConfiguration configuration because the dependency injection needs to know the database context to resolve the injected database context in the repository. – Golden Lion Aug 05 '20 at 17:26
  • Adding the ef contexts allowed the dependency injection to complete. However, the UseSqlServer for sql server does not correctly keep the connection string for AContext when you look at AContext.Database.GetDBConnection. I need to know why AddDbContext did not keep the connection strings separate. – Golden Lion Aug 05 '20 at 17:36
  • correct. I need to complete startup.cs – Golden Lion Aug 26 '20 at 15:00

2 Answers2

3

I was able to get the dependency injection to work in xunit once I added the startup.cs code

Solution startup.cs file in your XUnit Project:

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{

var configuration = new ConfigurationBuilder()
        .SetBasePath(System.IO.Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", false, true)
        .Build();

                
    var connectionString =     configuration.GetConnectionString("A_DbCoreConnectionString");
    services.AddDbContext<AContext>(options1 => options1.UseSqlServer(connectionString));

    connectionString= configuration.GetConnectionString("B_DbCoreConnectionString");
    services.AddDbContext<BContext>(options2 => options2.UseSqlServer(connectionString));

    services.AddTransient<IARepository, ARepository>();
    services.AddTransient<IBRepository, BRepository>();
  }
 }
Golden Lion
  • 3,840
  • 2
  • 26
  • 35
  • Seems you answered your own question. Could you move your answer (i.e. what answers your question) to here so it is clear what the original problem was and what part solved it - making it clear for other readers (like me)... – Matt Nov 24 '20 at 09:53
  • Thanks, but it still doesn't work for me. I created classes AContext: DbContext and BContext: DbContext, IARepository and IBRepository as well as ARepository and BRepository and added ConfigureServices. But UseSqlServer is showing Compiler Error CS1061. Any guidance for this? – Matt Nov 25 '20 at 13:52
  • Why do you think your getting a compiler error? – Golden Lion Nov 28 '20 at 13:56
  • CS1061 error means that method `.UseSqlServer` does not exist. I googled a bit and found that this method is included in `Microsoft.EntityFrameworkCore.SqlServer`, which need to be downloaded additionally. I thought that `Microsoft.EntityFrameworkCore` would include that method, but it doesn't. – Matt Nov 30 '20 at 08:40
  • I had a similar issue with `.UseSqlServer` in [this DbFixture](https://stackoverflow.com/questions/50921675/dependency-injection-in-xunit-project), but now it is solved. – Matt Nov 30 '20 at 09:03
2

In .Net 6 and later Startup.cs dont work automatically.

The minimun setup required is to create a ServiceCollection and build it to a ServiceProvider:

public class EfRepositoryTests
{
    private ServiceProvider services;

    public EfRepositoryTests()
    {
        var serviceCollection = new ServiceCollection();

        serviceCollection.AddDbContext<BloggingContext>(ServiceLifetime.Singleton);
        serviceCollection.AddSingleton<EfRepository<Blog>>();

        this.services = serviceCollection.BuildServiceProvider();
    }

    [Fact]
    public async Task CreateAsync()
    {

        var ctx = this.services.GetRequiredService<BloggingContext>();
        var repository = this.services.GetRequiredService<EfRepository<Blog>>();

        //...
    }
}
Murilo Maciel Curti
  • 2,677
  • 1
  • 21
  • 26