Blake Rivell
Blake Rivell

Reputation: 13875

Creating a TestServer and using Dependency Injection with XUnit and ASP.NET Core 1.0

I have an ASP.NET Core 1.0 Solution with the following project structure:

Web App (ASP.NET MVC6)
BusinessLibrary (Class Library Package)
DataLibrary(Class Library Package)
Tests (Class Library Package w/ XUnit)

I am attempting to use Microsoft's new built-in dependency injection all throughout the entire system.

Here is how everything currently flows from my ASP.NET MVC App all the way down to my Repository layer

//Startup.cs of MVC Web App
public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    services.AddSingleton(_=> Configuration);

    services.AddTransient<ICustomerService, CustomerService>();
    services.AddTransient<ICustomerRepository, CustomerRepository>();
}

public class CustomersController : Controller
{
    private ICustomerService _service;
    public CustomersController(ICustomerService service)
    {
        _service= service;
    }
}

public class CustomerService : ICustomerService
{
    private ICustomerRepository _repository;
    public PriceProtectionManager(ICustomerRepository repository)
    {
        _repository = repository;
    }
}

public class CustomerRepository : BaseRepository, ICustomerRepository
{
    public CustomerRepository(IConfigurationRoot config) 
    : base(config)
    {
    }
}

public class BaseRepository
{
    private IConfigurationRoot _config;

    public BaseRepository(IConfigurationRoot config)
    {
        _config = config;
    }
}

Now how can I get something similar to work with XUnit project so I can access CustomerService and call the functions?

Here is what my Fixture class looks like:

public class DatabaseFixture : IDisposable
{
    public ICustomerService CustomerService;
    public DatabaseFixture(ICustomerService service)
    {
        CustomerService = service;
    }

    public void Dispose()
    {

    }
}

The problem is that ICustomerService is unable to be resolved... This is probably because I don't have a Startup.cs like my WebApp. How do I replicate this behavior with the test project? I don't know where to create my TestServer because if I do it in the fixture it will be too late.

Upvotes: 5

Views: 5154

Answers (1)

Danny van der Kraan
Danny van der Kraan

Reputation: 5366

Well, you can provide your own dependencies to your SUT (which is the way you should want it IMHO). I've just answered a similar question here.

If you want to define your connectionstring at one place you could use xUnit's ability to use shared context (fixtures).

Update: Examples incorperating fixtures and DI...

Your testclass should implement IClassFixture and contain for example the following fields and constructor:

    public class AspnetCoreAndXUnitPrimeShould: IClassFixture<CompositionRootFixture>
{
    private readonly TestServer _server;
    private readonly HttpClient _client;
    private readonly CompositionRootFixture _fixture;

    public AspnetCoreAndXUnitPrimeShould(CompositionRootFixture fixture) 
    {
        // Arrange
        _fixture = fixture;
        _server = new TestServer(TestServer.CreateBuilder(null, app =>
        {
            app.UsePrimeCheckerMiddleware();
        },
            services =>
            {
                services.AddSingleton<IPrimeService, NegativePrimeService>();
                services.AddSingleton<IPrimeCheckerOptions>(_ => new AlternativePrimeCheckerOptions(_fixture.Path));
            }));
        _client = _server.CreateClient();
    }

Notice that AspnetCoreAndXUnitPrimeShould is the name of the testclass in my example. The fixture looks like:

    public class CompositionRootFixture
{
    public string Path { get; }

    public CompositionRootFixture()
    {
        Path = "@/checkprime";
    }
}

This is just a quick adoptation from another example, but you should understand how you can fix your problem now. AlternativePrimeCheckerOptions takes a string in the constructor, just like your Configuration class could. And with a fixture you arrange this connectionstring at one place.

Update Sample: https://github.com/DannyvanderKraan/ASPNETCoreAndXUnit

Upvotes: 3

Related Questions