![](/img/trans.png)
[英]How to Unit test Spring-Boot REST endpoints with MockMVC where the path mappings are environment variables?
[英]Spring Boot - REST controller, test with MockMvc, Environment properties
我在Spring Boot應用程序中有一個REST控制器,簡而言之:
@RestController
@RequestMapping("/api")
public class MyRestController {
@Autowired
private Environment env;
private String property1;
@PostConstruct
private void init() {
this.property1 = env.getProperty("myproperties.property_1");
}
@GetMapping("/mydata")
public String getMyData() {
System.out.println("property1: " + this.property1);
...
}
在application.yml中,我定義了類似於以下內容的屬性:
myproperties:
property_1: value_1
當我使用REST控制器時,它會按預期工作,會讀取值value_1,並存在GET方法中。
現在我想用單元測試來測試它,也是如此:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyApp.class)
public class MyRestControllerTest {
@Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;
@Autowired
private PageableHandlerMethodArgumentResolver pageableArgumentResolver;
@Autowired
private ExceptionTranslator exceptionTranslator;
private MockMvc restMyRestControllerMockMvc;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
final MyRestController myRestController = new MyRestController();
this.restMyRestControllerMockMvc = MockMvcBuilders.standaloneSetup(myRestController)
.setCustomArgumentResolvers(pageableArgumentResolver).setControllerAdvice(exceptionTranslator)
.setConversionService(createFormattingConversionService()).setMessageConverters(jacksonMessageConverter)
.build();
}
@Test
public void getMyDataTest() throws Exception {
restMyRestControllerMockMvc.perform(get("/api/mydata"))
.andExpect(status().isOk());
}
執行測試中的方法時,屬性property1的值為null。
這是為什么?
上面的代碼部分是由JHipster生成的,我不確定這是否是最佳解決方案,請重新使用它。
謝謝!
MockMvcBuilders.standaloneSetup無法加載SpringContext,因此屬性數據不可用。 您可以通過在MyRestControllerTest內部直接使用@Value(“ $ {myproperties.property_1}”)批注進行驗證-它將返回“ value_1”值(但在MyRestController內部-將返回null)。
請將其更改為MockMvcBuilders.webAppContextSetup並注入WebApplicationContext。 (最終,您可以通過它的構造函數將Environment Bean注入MyRestController中,但我認為這是Spring hacking。)
警告:還請記住(在Maven布局項目中)application.yml需要復制到src / test / resources。
代碼示例:
@RestController
@RequestMapping("/api")
public class MyRestController {
@Autowired
private Environment env;
private String envProperty;
@Value("${myproperties.property_1}")
private String valueProperty;
@PostConstruct
private void init() {
this.envProperty = env.getProperty("myproperties.property_1");
}
@GetMapping("/mydata")
public String getMyData() {
System.out.println("envProperty: " + this.envProperty);
System.out.println("valueProperty: " + this.valueProperty);
return "";
}
@GetMapping("/myproblem")
public String getMyProblem() {
throw new IllegalArgumentException();
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyApp.class)
public class MyRestControllerTest {
private MockMvc restMyRestControllerMockMvc;
@Autowired
private WebApplicationContext context;
@Before
public void setup() {
final MyRestController myRestController = new MyRestController();
// this.restMyRestControllerMockMvc = MockMvcBuilders.standaloneSetup(myRestController)
// .build();
this.restMyRestControllerMockMvc = MockMvcBuilders.webAppContextSetup(context)
.build();
}
@Test
public void getMyDataTest() throws Exception {
restMyRestControllerMockMvc.perform(get("/api/mydata"));
}
@Test
public void getMyProblemTest() throws Exception {
restMyRestControllerMockMvc.perform(get("/api/myproblem"))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isConflict());
}
}
@ControllerAdvice
public class ControllerAdvicer {
@ResponseStatus(HttpStatus.CONFLICT)
@ExceptionHandler(IllegalArgumentException.class)
public String assertionException(final IllegalArgumentException e) {
return "xxx";
}
}
使用@Value
批注從您的app.yml中讀取值
@RestController
@RequestMapping("/api")
public class MyRestController {
@Autowired
private Environment env;
@Value("${myproperties.property_1}")
private String property1;
@GetMapping("/mydata")
public String getMyData() {
System.out.println("property1: " + this.property1);
...
}
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
我將kasopey答案標記為正確,因為它包含完整答案,盡管其他響應者的答案在某些方面也是正確的。
但是我仍然想知道這些行是做什么用的:
.setCustomArgumentResolvers(pageableArgumentResolver)
.setControllerAdvice(exceptionTranslator)
.setConversionService(createFormattingConversionService())
.setMessageConverters(jacksonMessageConverter)
因為與您的解決方案一起使用
MockMvcBuilders.webAppContextSetup(context)
這些方法不可用。 如有必要,如何實現相同?
我的示例代碼中缺少的方法如下所示:
... Create a FormattingConversionService which use ISO date format, instead of the localized one.
public static FormattingConversionService createFormattingConversionService() {
DefaultFormattingConversionService dfcs = new DefaultFormattingConversionService ();
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setUseIsoFormat(true);
registrar.registerFormatters(dfcs);
return dfcs;
}
同樣,大部分代碼是由JHipster生成的,這很方便,但並不總是清楚原因和目的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.