2016-08-15 38 views
1

Spring Boot 1.4具有許多很好的功能,包括@DataJpaTest註釋,可以自動喚醒用於測試目的的類路徑嵌入式數據庫。據我所知,它不會與TestRestTemplate在同一類的邊界中結合使用。Spring Boot 1.4 - 如何通過驗證來測試控制器

下面的測試將無法正常工作:

@RunWith(SpringRunner.class) 
@SpringBootTest 
@DataJpaTest 
public class PersonControllerTest { 

    private Logger log = Logger.getLogger(getClass()); 

    private Category category; 

    @Autowired 
    private TestRestTemplate restTemplate; 

    @Autowired 
    private TestEntityManager entityManager; 

    @Before 
    public void init() { 

     log.info("Initializing..."); 

     category = entityManager.persist(new Category("Staff")); 
    } 

    @Test 
    public void personAddTest() throws Exception { 

     log.info("PersonAdd test starting..."); 

     PersonRequest request = new PersonRequest("Jimmy"); 

     ResponseEntity<String> response = restTemplate.postForEntity("/Person/Add", request, String.class); 
     assertEquals(HttpStatus.OK, response.getStatusCode()); 

     log.info("PersonAdd test passed"); 
    } 

在測試過程中的,會引發異常的啓動:

Unsatisfied dependency expressed through field 'restTemplate': 
No qualifying bean of type [org.springframework.boot.test.web.client.TestRestTemplate] 

然後猜測,切換到基於推薦模擬切片的方法,但它將不會在那裏工作,因爲控制器看起來像這樣:

@RequestMapping(value="/Person/Add", method=RequestMethod.POST) 
public ResponseEntity personAdd(@Valid @RequestBody PersonRequest personRequest, 
           Errors errors) 

    personValidator.validate(personRequest, errors): 

    if (errors.hasErrors()) 
     return new ResponseEntity(HttpStatus.BAD_REQUEST); 

    personService.add(personRequest); 

    return new ResponseEntity(HttpStatus.OK); 
} 

...很容易根據文檔建議嘲笑personService,但如何與errors對象在這種情況下不可嘲笑?據我所知,沒有辦法嘲笑它,因爲它不是類字段或方法的返回值。

所以,我不能使用分片方法或集成方法來測試上面的代碼,因爲@DataJpaTest不應該與控制器一起使用。

有沒有一種方法可以使用Spring Boot 1.4測試功能來測試這種架構的控制器?

+0

而不是嘲笑控制器的方法,你可以模擬URL調用。這將負責錯誤驗證。檢查這篇文章http://stackoverflow.com/a/12308698/5343269 – 11thdimension

+0

@ 11thdimension值得指出的是,在Spring Boot 1.4中,註釋略有改變,您不需要創建MockMvc,而是可以自動裝入。詳情請參閱https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4。 –

+0

@wilddev如果你可以包含你正在嘗試使用的測試類,那麼我們可以提供一些關於如何使它以你期望的方式工作的建議。 –

回答

3

您對@DataJpaTest的理解有點偏離。從文檔「僅當測試只關注JPA組件時才能使用」。如果您想測試控制器層,則不需要使用此註釋,因爲沒有任何WebMvc組件會加載到應用程序上下文中。您反而想使用@WebMvcTest並使用您正在測試的@Controller

@RunWith(SpringRunner.class) 
@WebMvcTest(PersonController.class) 
public class PersonControllerTest { 
    @Autowired 
    private MockMvc mockMvc; 

    @MockBean 
    PersonValidator personValidator; 

    @MockBean 
    PersonService personService; 

    @Test 
    public void personAddTest() throws Exception { 
     String content = "{\"name\": \"Jimmy\"}"; 
     mockMvc.perform(post("/Person/Add").contentType(MediaType.APPLICATION_JSON).characterEncoding("UTF-8") 
       .accept(MediaType.APPLICATION_JSON).content(content)).andExpect(status().isOk()); 
    } 

    @Test 
    public void personAddInvalidTest() throws Exception { 
     String content = "{\"noname\": \"Jimmy\"}"; 
     mockMvc.perform(post("/Person/Add").contentType(MediaType.APPLICATION_JSON).characterEncoding("UTF-8") 
       .accept(MediaType.APPLICATION_JSON).content(content)).andExpect(status().isBadRequest()); 
    } 
} 

不知道你如何連接驗證器和服務,所以只是假設你自動裝配它們。

@Controller 
public class PersonController { 
    private PersonValidator personValidator; 
    private PersonService personService; 

    public PersonController(PersonValidator personValidator, PersonService personService) { 
     this.personValidator = personValidator; 
     this.personService = personService; 
    } 

    @RequestMapping(value = "/Person/Add", method = RequestMethod.POST) 
    public ResponseEntity<String> personAdd(@Valid @RequestBody PersonRequest personRequest, Errors errors) { 
     personValidator.validate(personRequest, errors); 

     if (errors.hasErrors()) { 
      return new ResponseEntity<String>(HttpStatus.BAD_REQUEST); 
     } 
     personService.add(personRequest); 

     return new ResponseEntity<String>(HttpStatus.OK); 
    } 
} 

樣本PersonRequest因爲我不知道那裏還有什麼東西。請注意,名稱上的一個驗證爲@NotNull,因爲我想要展示如何使用Errors對象的方法。

public class PersonRequest { 
    @NotNull 
    private String name; 

    public PersonRequest() { 
    } 

    public PersonRequest(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 
相關問題