使用 Spring 引导测试 REST 控制器的 Spock 测试框架

Spock Testing Framework with Spring Boot to test REST Controller

我已经使用 spring 引导编写了 rest api 这是控制器代码

    @RestController
    public class ApiController {
    
        @Autowired
        private ApiService apiService;
        
            @PostMapping(path = "/user", consumes = {MediaType.APPLICATION_JSON_VALUE}, 
produces = {MediaType.APPLICATION_JSON_VALUE})
        @LogTransaction
        public ResponseEntity<String> user(HttpServletRequest request) {
               //apiService.getUser() method call database so i need to mock  it 
               USer user = apiService.getUser(request);
              return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(user);
        }
    }
    

这个 api 工作正常,我已经在 groovy

中使用 spock 框架编写了测试
    @SpringBootTest
    class ApiControllerTest extends Specification {
    
    @Autowired
    private ApiController apiController;
    
    @Autowired
    private ApiService apiService;
    
    
    @Autowired
    MockMvc mockMvc
        
    def "User api"() {
            given:
            def User user = new User()      
            apiService.getUser(_) >> user
    
            when:
            def result = mockMvc.perform(MockMvcRequestBuilders
                    .post("/user")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content("""
    {
     "username":"demo",
     "password":"demo"
    }
    """))
                    .andReturn()
    
            then:
            assert result.response.status == HttpStatus.OK.value()
    
    }

这也很好用。方法 apiService.getUser(请求) 调用数据库。我想嘲笑它。但它每次都在调用数据库。因此,我尝试在此处使用 @Autowired 模拟 apiService.getUser(request),但它对我不起作用,并且此方法每次都执行并调用数据库。任何人都可以分享模拟控制器的 apiService.getUser(request) 方法的方法。

您可以对

这样的数据源使用排除
@SpringBootTest
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
@AutoConfigureMockMvc
public class Class1Test{
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private RestTemplate restTemplate;

    @MockBean
    private IYourRepository repository;

    @Autowired
    private SecurityJwtSettings securityJwtSettings;


使用 mockito,您可以模拟对数据库的请求:

Mockito.doAnswer(x->{
            YourEntity entityToSave = x.getArgument(0);
            entityToSave.setCreatedAt(LocalDateTime.now());
            Assert.assertEquals("tester.admin.01",entityToSave.getAuthorizedBy());
            Assert.assertEquals("tester.01", entityToSave.getRequestedBy());
            return entityToSave;
        }).when(repository).save(Mockito.any(YourEntity.class));

您可以通过使用 @SpringSpy.

注释来部分模拟 spring 个 bean

因此,在您的情况下,您只需将 @Autowired 替换为 @SpringSpy:

  @SpringSpy
  private ApiService apiService;

它应该可以工作。