NUnit 5 Spring MVC 测试 NoSuchBeanDefinitionException 用于子模块中的 Autowired 依赖项

Posted

技术标签:

【中文标题】NUnit 5 Spring MVC 测试 NoSuchBeanDefinitionException 用于子模块中的 Autowired 依赖项【英文标题】:NUnit 5 Spring MVC test NoSuchBeanDefinitionException for Autowired dependency in submodule 【发布时间】:2020-06-09 19:38:45 【问题描述】:

我有一个包含两个子模块的项目;一个是数据访问层,另一个是 API 服务。 数据访问模块在服务类中使用 JOOQ 和自动装配的 DSLContext。另外,我使用的是 JUnit 5 和 Spring Boot 2.2.4。

数据访问模块中的QueryService类有@Autowired private DSLContext dsl这样的成员;

测试类是这样设置的:

@SpringBootTest
public class MyServiceTests 

  @Autowired
  QueryService service;

  @Autowired
  private DSLContext dsl;

  @Test
  public void TestDoSomething() throws Exception 
    service.selectBusinessEntityRelatedByBusinessEntity("C00001234", mockAuth);
  

此模块中的测试运行正确。配置从 application.yaml 中读取,并且 autowire 将真实服务或模拟注入到我的 QueryService 和本地 dsl 中。

API 服务是另一回事。如果我在没有 MVC 的情况下使用 @SpringBootTest 注释,我可以成功地让测试注入本地 DSLContext,并使用来自 application.yaml 的配置。类似这样的测试设置:

@SpringBootTest
public class CustomersControllerTests 

  @Autowired
  private Gson gson;

  @Autowired
  DSLContext dsl;

  @Test
  public void addCustomerTest() 
  

我需要的是使用 @WebMvcTest 以便初始化 MockMvc 但切换到 @WebMvcTest 会导致在数据访问模块中实现的服务类中注入失败。注入未能在查询服务类中找到 DSLContext bean。我这样设置测试:

@WebMvcTest
public class CustomersControllerTests 

  @Autowired
  private MockMvc mockMvc;

  @Autowired
  private Gson gson;

  private static final String testSub = "329e6764-3809-4e47-ac48-a52881045787";

  @Test
  public void addCustomerTest() 

    var newCustomer = new Customer().firstName("John").lastName("Doe");
    mockMvc.perform(post("/customers").content(gson.toJson(newCustomer)).contentType(MediaType.APPLICATION_JSON)
        .with(jwt().jwt(jwt -> jwt.claim("sub", testSub)))).andExpect(status().isNotImplemented());
  

这是实际的错误:

2020-02-25 18:14:33.655  WARN 10776 --- [           main] o.s.w.c.s.GenericWebApplicationContext   : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customersController': Unsatisfied dependency expressed through field '_customersService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customersService': Unsatisfied dependency expressed through field '_queryService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'queryService': Unsatisfied dependency expressed through field '_dsl'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.jooq.DSLContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: @org.springframework.beans.factory.annotation.Autowired(required=true)

所以,我知道测试应用程序配置是正确的,因为它在不使用 MVC 注释时有效。另外,我可以在 API 项目测试中创建一个 DSLContext,我实际上可以在测试之外运行 API 服务。

那么,为什么在使用 MVC 测试设置时找不到 DSLContext 呢?

【问题讨论】:

【参考方案1】:

这可能是因为@WebMvcTest 完全禁用了 Spring Boot 的自动配置,并且只扫描了 @Controllers 和其他一些选择类,这是您的 ..well...MVC 测试所需要的......

Spring 文档建议在您的情况下这样做:

如果您希望加载完整的应用程序配置并使用 MockMVC,则应考虑将 @SpringBootTest 与 @AutoConfigureMockMvc 结合使用,而不是使用此注解。

【讨论】:

以上是关于NUnit 5 Spring MVC 测试 NoSuchBeanDefinitionException 用于子模块中的 Autowired 依赖项的主要内容,如果未能解决你的问题,请参考以下文章

C# - 单元测试 - 初始化私有字段 - ASP.NET Core 5 - NUnit 测试

无法将 ReactiveUI 添加到 NUnit 测试项目

Spring MVC 5 ResultMatcher jsonPath 空值

单元测试之NUnit一

单元测试之NUnit二

使用参数并行运行 nunit 测试 (nunit 3.8.x)