Можно ли использовать инъекцию зависимостей с помощью xUnit?
У меня есть тестовый класс с конструктором, который нуждается в IService.
public class ConsumerTests
{
private readonly IService _service;
public ConsumerTests(IService servie)
{
_service = service;
}
[Fact]
public void Should_()
{
//use _service
}
}
Я хочу подключить мой контейнер DI к выбору для создания тестового класса.
Возможно ли это с помощью xUnit?
Ответы
Ответ 1
Существует способ сделать это, используя пакет nuget из этого исходного кода: https://github.com/dennisroche/xunit.ioc.autofac
Он отлично работает, пока вы используете [Fact]
, но затем я заблокирован, когда начал использовать [Theory]
. Существует запрос на растяжение, чтобы разобраться с этим.
Чтобы разблокировать себя, я использовал CollectionFixture для ввода Контейнера и из контейнера, я разрешаю интерфейс.
Ответ 2
Да, теперь, эти два вопроса и ответы должны быть объединены, на мой взгляд, ответ здесь
Net Core: выполнить все внедрения зависимостей в тесте Xunit для AppService, репозитория и т.д.
Используйте пользовательскую фабрику веб-приложений и ServiceProvider.GetRequiredService ниже, не стесняйтесь редактировать и оптимизировать ответ
CustomWebApplicationFactory:
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration((hostingContext, configurationBuilder) =>
{
var type = typeof(TStartup);
var path = @"C:\\OriginalApplication";
configurationBuilder.AddJsonFile($"{path}\\appsettings.json", optional: true, reloadOnChange: true);
configurationBuilder.AddEnvironmentVariables();
});
// if you want to override Physical database with in-memory database
builder.ConfigureServices(services =>
{
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
services.AddDbContext<ApplicationDBContext>(options =>
{
options.UseInMemoryDatabase("DBInMemoryTest");
options.UseInternalServiceProvider(serviceProvider);
});
});
}
}
Интеграционный тест:
public class DepartmentAppServiceTest : IClassFixture<CustomWebApplicationFactory<OriginalApplication.Startup>>
{
public CustomWebApplicationFactory<OriginalApplication.Startup> _factory;
public DepartmentAppServiceTest(CustomWebApplicationFactory<OriginalApplication.Startup> factory)
{
_factory = factory;
_factory.CreateClient();
}
[Fact]
public async Task ValidateDepartmentAppService()
{
using (var scope = _factory.Server.Host.Services.CreateScope())
{
var departmentAppService = scope.ServiceProvider.GetRequiredService<IDepartmentAppService>();
var dbtest = scope.ServiceProvider.GetRequiredService<ApplicationDBContext>();
dbtest.Department.Add(new Department { DepartmentId = 2, DepartmentCode = "123", DepartmentName = "ABC" });
dbtest.SaveChanges();
var departmentDto = await departmentAppService.GetDepartmentById(2);
Assert.Equal("123", departmentDto.DepartmentCode);
}
}
}
ресурсы:
https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2
https://fullstackmark.com/post/20/painless-integration-testing-with-aspnet-core-web-api
Ответ 3
Что вы пытаетесь проверить? Внедрение IService
или проводка контейнера DI?
Если вы IService
реализации IService
, вы должны создавать их экземпляры непосредственно в тесте (и проверять любые зависимости):
var service = new MyServiceImplementation(mockDependency1, mockDependency2, ...);
// execute service and do your asserts, probably checking mocks
Если вы пытаетесь проверить проводку контейнера DI, вам нужно обратиться и явно взять настроенный контейнер. Не существует "корня композиции", который бы сделал это для вас (следует псевдокод, со вкусом Autofac):
var myContainer = myCompositionRoot.GetContainer();
var service = myContainer.ResolveCompnent<IService>();
// execute service and do your asserts with the actual implementation
Если вы используете xUnit для запуска интеграционных тестов, когда вам нужно использовать один и тот же объект в нескольких тестах, посмотрите на Fixtures: http://xunit.github.io/docs/shared-context.html.
Ответ 4
Вы можете использовать Xunit.DependencyInjection