【问题标题】:Springboot integration tests are failing when adding multiple service添加多个服务时,Spring Boot 集成测试失败
【发布时间】:2021-07-21 23:41:36
【问题描述】:

我有一个 Spring Boot 应用程序,它具有一个控制器类、一个服务和一个存储库,运行良好。我已经为此添加了 Junit 测试用例,而且效果也很好。

@RestController
public class EmployeeController{
    @Autowired
    EmployeeService service;

    @GetMapping("/list")
    public List<Employee> getEmployee(){
       return service.findAll();
    }
}


@Service
public class EmployeeService{
   
   @Autowired
   EmployeeRepository repository;

   public List<Employee> findAll(){
      return repository.findAll();
   }
}

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, String>{}

测试类如下。

@RunWith(SpringRunner.class)
@WebMvcTest(value = EmployeeController.class)
class EmployeeControllerIntegrationTest {
    @Autowired
    private MockMvc mvc;

    @MockBean
    private EmployeeService service;

    @Test
    public void findAllEmployeeTest(){
    }
}

测试用例一直通过,但目前我正在添加另一个 API,因为下面所有测试都失败了。

@RestController
public class DepartmentController{
    @Autowired
    DepartmentService service;

    @GetMapping("/list")
    public List<Department> getDepartment(){
       return service.findAll();
    }
}


@Service
public class DepartmentService{
   
   @Autowired
   DepartmentRepository repository;

   public List<Department> findAll(){
      return repository.findAll();
   }
}
@Repository
public interface DepartmentRepository extends JpaRepository<Department, String>{}

测试类如下。

@RunWith(SpringRunner.class)
@WebMvcTest(value = DepartmentController.class)
class DepartmentControllerIntegrationTest {
    @Autowired
    private MockMvc mvc;

    @MockBean
    private DepartmentService service;

    @Test
    public void findAllDepartmentTest(){
    }
}

添加部门服务测试用例后失败并出现以下错误:

Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'departmentController': Unsatisfied dependency expressed through field 'departmentService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'departmentService': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.employeeapp.data.repository.DepartmentRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

干杯!

【问题讨论】:

    标签: java spring-boot junit integration-testing rest


    【解决方案1】:

    No qualifying bean of type 'com.employeeapp.data.repository.DepartmentRepository' available: expected at least 1 bean which qualifies as autowire candidate.

    Spring 寻找 TYPE 的 bean:DepartmentRepository

    1. 定义 Bean
    @Repository
    public interface DepartmentRepository extends JpaRepository<Department, String>{}
    

    在此处添加注解@Repository,以便Spring可以将DepartmentRepository变成一个Bean。

    1. 自动装配正确的类型和名称
    @Service
    public class DepartmentService{
       
       @Autowired
       private DepartmentRepository repository; // The best practice is to write the full bean name here departmentRepository.
    
       public List<Department> findAll(){
          return repository.findAll();
       }
    }
    

    【讨论】:

      【解决方案2】:

      就我所见,您尝试通过模拟您的服务来进行 IT 测试。在 IT 测试中,您不会模拟您的服务。在集成测试中,您测试所有这些都可以一起工作。如果您不模拟存储库,它更像是一个 E2E 测试(端到端测试所有交互路径)。

      如果没有要测试的逻辑和/或不想写入数据库,您可以模拟存储库。

      所以如果是单元测试,你可以试试(它适用于我的项目),我使用 Junit 5 (org.junit.jupiter)

      
          @WebMvcTest(DepartementController.class)
          public class DepartementControllerTest {
          
            @MockBean
            private DepartmentService departmentService;
          
          
            @Autowired
            MockMvc mockMvc;
          
          @Test
          public void findAllTest(){
           // You can create a list for the mock to return
          when(departmentService.findAll()).thenReturn(anyList<>);
          
          //check if the controller return something
          assertNotNull(departmentController.findAll());
          
          //you check if the controller call the service
          Mockito.verify(departmentService, Mockito.times(1)).findAll(anyList());
          }
      
      

      这是一个单元测试。

      It 测试会更像

      
          @ExtendWith(SpringExtension.class)
          @SpringBootTest
          public class DepartmentIT {
          
          
            @Autowired
            DepartmentService departmentService;
          
            @Autowired
            private WebApplicationContext wac;
          
            private MockMvc mockMvc;
          
            @BeforeEach
            void setUp() {
              this.mockMvc =
                      MockMvcBuilders.webAppContextSetup(this.wac)
                              .build();
            }
          
            @Test
            void departmentFindAll() throws Exception {
              MvcResult mvcResult = this.mockMvc.perform(get("/YOUR_CONTROLLER_URL")
                      .contentType(MediaType.APPLICATION_JSON))
                      .andExpect(status().is(200))
                      .andReturn();
          
              
      assertTrue(mvcResult.getResponse().getContentAsString().contains("SOMETHING_EXPECTED"));
              assertTrue(mvcResult.getResponse().getContentAsString().contains("SOMETHING_EXPECTED"));
              assertTrue(mvcResult.getResponse().getContentAsString().contains("SOMETHING_EXPECTED"));
          
          //You also can check its not an empty list, no errors are thrown etc...
          
            }
      
      

      进口使用所以你不要搜索太多是

      
      import org.junit.jupiter.api.Assertions;
      import org.junit.jupiter.api.BeforeEach;
      import org.junit.jupiter.api.Test;
      import org.junit.jupiter.api.extension.ExtendWith;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.boot.test.context.SpringBootTest;
      import org.springframework.http.MediaType;
      import org.springframework.test.context.junit.jupiter.SpringExtension;
      import org.springframework.test.web.servlet.MockMvc;
      import org.springframework.test.web.servlet.MvcResult;
      import org.springframework.test.web.servlet.setup.MockMvcBuilders;
      import org.springframework.web.context.WebApplicationContext;
      
      import static org.junit.jupiter.api.Assertions.*;
      import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
      import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
      import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
      import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
      
      

      【讨论】:

        猜你喜欢
        • 2019-12-26
        • 1970-01-01
        • 2017-07-02
        • 2020-03-18
        • 2021-03-20
        • 1970-01-01
        • 2015-08-02
        • 2015-06-24
        • 1970-01-01
        相关资源
        最近更新 更多