Reputation: 13875
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
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