添加多个服务时,Spring Boot 集成测试失败
Posted
技术标签:
【中文标题】添加多个服务时,Spring Boot 集成测试失败【英文标题】:Springboot integration tests are failing when adding multiple service 【发布时间】: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)
干杯!
【问题讨论】:
【参考方案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
。
-
定义 Bean
@Repository
public interface DepartmentRepository extends JpaRepository<Department, String>
在此处添加注解@Repository
,以便Spring可以将DepartmentRepository
变成一个Bean。
-
自动装配正确的类型和名称
@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;
【讨论】:
以上是关于添加多个服务时,Spring Boot 集成测试失败的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot + 云 | Zuul 代理 |集成测试
Spring Boot JPA 元模型不能为空!尝试运行 JUnit / 集成测试时