【问题标题】:Net Core: Dependency Injection in Integration Test [duplicate]Net Core:集成测试中的依赖注入
【发布时间】:2019-07-31 08:26:48
【问题描述】:

如何在集成测试中进行依赖注入? 调用departmentRepositorydepartmentAppService,给我null 和下面的错误。

public class DepartmentAppServiceTest
{
    public SharedServicesContext context;
    public IMapper mapper;
    public IRepository<Department, int> departmentRepository;
    public IDepartmentAppService departmentAppService;

    public DepartmentAppServiceTest()
    {
        ServiceCollection services = new ServiceCollection();
        services.AddTransient<IRepository<Department>, BaseRepository<Department>>();
        services.AddTransient<IDepartmentAppService, DepartmentAppService>();

调试和设置断点,调用这个仓库或者app服务都是null,

新方法

 [Fact]
 var departmentDto = await departmentAppService.GetDepartmentById(2);

应用服务的构造函数

DepartmentAppService(departmentRepository, mapper)
DepartmentRepository(dbcontext)

错误:

消息:System.NullReferenceException:对象引用未设置为 一个对象的实例。

【问题讨论】:

  • @Izzy 我可以在实际程序中运行依赖注入,但不能在 xunit 中运行,您的链接不相关,并导致出现问题,谢谢
  • 看看here
  • 顺便可以用这个services.AddTransient&lt;IRepository&lt;&gt;, BaseRepository&lt;&gt;&gt;();
  • Unit Testing IServiceCollection Registration 的可能重复项,这说明了如何使用依赖注入进行单元测试

标签: c# asp.net-core .net-core xunit


【解决方案1】:

对于我们的集成测试,我们以编程方式启动应用程序并使用 HttpClient 对 API 端点进行调用。这样,您的应用程序将运行整个启动过程,并且依赖注入就像魅力一样工作。

这是服务器启动和客户端创建的示例,它可以重复用于多个测试:

_server = new TestServer(new WebHostBuilder()
                .UseEnvironment("Testing")
                .UseContentRoot(applicationPath)
                .UseConfiguration(new ConfigurationBuilder()
                    .SetBasePath(applicationPath)
                    .AddJsonFile("appsettings.json")
                    .AddJsonFile("appsettings.Testing.json")
                    .Build()
                )
                .UseStartup<TestStartup>());
_client = _server.CreateClient();
// Act
var response = await _client.GetAsync("/");

// Assert
response.EnsureSuccessStatusCode();

Microsoft 也使用 HttpClient 记录了这一点:
https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2

【讨论】:

  • 嗨@Yush0 你能复习一下这个问题吗?它不起作用
  • 实际上,您可以使用正在测试的应用程序中的 Startup 类(.UseStartup() 而不是 TestStartup),然后使用如下服务:myService = _server.Services.GetRequiredService ();
  • @Ewertonews:是的,这也有效。在我的例子中,我从 Startup 继承了 TestStartup 来覆盖一些关于身份验证的功能。
  • 嗯..不错..没错。
【解决方案2】:

如果您使用 departmentAppService 局部变量,则为 null。您的对象在容器中。您可以通过调用 GetRequiredService 或 GetService 方法来检索它。

我以这种方式在控制台应用程序中使用了 ServiceCollection。

IServiceCollection services = new ServiceCollection();

services.AddSingleton<IDepartmentAppService, DepartmentAppService>();

using (ServiceProvider serviceProvider = services.BuildServiceProvider())
{
  var departmentAppService = serviceProvider.GetRequiredService<IDepartmentAppService>();

  await departmentAppService.GetDepartmentById(2);
}

你应该关心的是,测试类正在为每个测试用例重新创建。

【讨论】:

  • 谢谢,这是我的事实课,那我该如何分开呢? var departmentDto = await departmentAppService.GetDepartmentById(2);
  • 还需要声明这个新的 DepartmentAppService(departmentRepository, mapper); ,我会更新问题
  • 这取决于您的需求。 1)在构造函数中,您可以创建容器并检索对象以初始化局部变量。 2) IClassFixture 是一个有用的功能,可以保留变量(不会丢失它们)。 3) ...
【解决方案3】:

使用 Moq,您将能够伪造依赖关系,然后将它们传递给您的服务。例如,您的测试方法可能如下所示:

//arrange  
var company = new company() { company_name = "TCS" };  

var mockRepo = new Mock<ICompany>();  
mockRepo.Setup(x => x.InsertCompany(company)).Returns(true);  

var companyObject = new Company(mockRepo.Object);  
var retrnData = companyObject.InsertCompany(company)

这段代码sn-p取自这篇文章,我建议你看看:

https://www.c-sharpcorner.com/UploadFile/dacca2/unit-test-using-mock-object-in-dependency-injection/

【讨论】:

  • 这是用于单元测试的,原始问题是关于集成测试的。集成测试应该针对真实数据库并返回真实数据,而不是模拟。这个想法是测试代码行执行时将执行的所有内容。
猜你喜欢
  • 2016-11-22
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
  • 2016-05-22
  • 1970-01-01
  • 2021-07-15
  • 1970-01-01
  • 2021-10-23
相关资源
最近更新 更多