我的REST API在POST請求上生成密碼並將其存儲在數據庫中。出於開發目的,我想將它放入響應中,在application.properties文件中將development.mode標誌設置爲true。更改單元測試方法中的應用程序屬性值
我想測試這個控制器,並檢查如果標誌爲真,密碼在響應中,如果爲false,則密碼不是。
我想知道是否以及如何從每個測試方法動態設置此屬性值。
這是我的控制器:
@RestController
public class PasswordController {
@Value("${development.mode}")
private boolean isDevelopmentMode;
@RequestMapping(value = "/new", method = RequestMethod.POST)
public ResponseEntity<String> generatePassword(@RequestParam(USERNAME_PARAM) String username) {
String password = manager.generatePassword();
String body = "";
if (isDevelopmentMode) {
body = "New password: " + password;
}
return new ResponseEntity<>(body, HttpStatus.OK);
}
}
我所看到的文檔定義測試不同的屬性文件,使用@PropertySource,但它是在類的級別,我想避免創建一個不同的文件只是爲了更換旗幟。
我也看過帖子說你可以使用ReflectionUtils.setField來改變私人字段的值,但爲此我必須明確地實例化我的控制器,並因此在Autowired字段中存在一些問題。我試過這個:
@RunWith(SpringRunner.class)
@WebMvcTest(PasswordControllerTest.class)
public class PasswordControllerTest extends OtpTest {
@Autowired
private MockMvc mockMvc;
@Test
public void newRoute_developmentModeIsFalse_responseBodyIsEmpty() throws Exception {
PasswordController controller = new PasswordController();
ReflectionTestUtils.setField(controller, "isDevelopmentMode", false);
MockMvc mvc = MockMvcBuilders.standaloneSetup(new PasswordController()).build();
given(manager.generatePassword(any(String.class))).willReturn("123456");
mvc.perform(post("/new").param(PasswordController.USERNAME_PARAM, "test_user")).andExpect(status().isOk()).andExpect(content().string(""));
}
}
是否有可能在每個測試方法中設置@Value字段的值?我應該重構我的代碼以不同的方式訪問它嗎?
SOLUTION 感謝鮑里斯·Zibrov其與此代碼的工作:
@RunWith(SpringRunner.class)
@WebMvcTest(PasswordController.class)
public class PasswordControllerTest extends OtpTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private WebApplicationContext applicationContext;
@Test
public void newRoute_developmentModeIsTrue_passwordIsInTheResponseBody() throws Exception {
PasswordController controller = applicationContext.getBean(PasswordController.class);
ReflectionTestUtils.setField(controller, "isDevelopmentMode", true);
given(manager.generatePassword(any(String.class))).willReturn("123456");
mockMvc.perform(post("/new").param(PasswordController.USERNAME_PARAM, "test_user")).andExpect(status().isOk())
.andExpect(content().string("New password: 123456"));
}
}
充分利用應用程序上下文我控制器豆起初不工作,因爲我在以前的代碼我是用我的測試類在WebMvcTest註釋中。
謝謝Borys的回覆。我不確定要理解:在您的解決方案中,如何在同一個測試類中進行2個單元測試,一個用於測試development.mode = true,另一個用false?我的理解是,我將不得不創建兩個類,2個applicationContext文件,我錯了嗎? –
嗯,是的,你需要創建兩個類。另一種選擇是使用ReflectionTestUtils,但從applicationContext中取出控制器,而不是直接實例化。 – borowis
或者您可以爲該字段提供一個設置器 – borowis