我正在使用一些會話范圍的 bean 對 Spring Boot MVC 控制器進行單元測驗,雖然應用程式按預期作業,但由于未知原因,單元測驗被證明很麻煩,我希望了解更多關于為什么。
bean 配置如下所示:
@Bean(name="scopedBean")
@Scope(value=WebApplicationContext.SCOPE_SESSION,
proxyMode=ScopedProxyMode.TARGET_CLASS)
public MyScopedBean myScopedBean() {
return new MyScopedBean();
}
控制器看起來像這樣:
@Autowired
private ISomeService service;
@Autowired
private MyScopedBean scopedBean;
@GetMapping("/")
public ModelAndView getRequest(ModelAndView model, @RequestParam("id") UUID id) {
if(scopedBean.matches(id)){
//do some stuff
}
//return a page
}
類中還有其他方法可以獲取、設定和檢查 scopedBean 中的值。
測驗看起來像這樣:
@WebMvcTest(MyController.class)
@Import({ActualValidator.class,SecurityConfig.class})
class MyControllerTest {
@MockBean
private MyUserDetailsService userDetailsService;
@MockBean
private ISomeService someService;
@MockBean
private MyScopedBean scopedBean;
@Test
void testA() throws Exception {
when(scopedBean.getAValue()).thenReturn("myvalue");
when(scopedBean.matches("someProperty").thenReturn(false);
mockMvc.perform(get("/"))
.andExpect(view().name("something");
}
@Test
void testB() throws Exception {
when(scopedBean.getAnotherValue()).thenReturn("othervalue");
when(scopedBean.matches("anotherProperty").thenReturn(true);
mockMvc.perform(get("/"))
.andExpect(view().name("somethingelse");
}
}
Each test, when ran individually, passes. When running them all together, they don't just fail, they return null pointers from inside the mocked proxy as if the object had been properly instantiated. I may be misunderstanding the concept of @MockBean but it was my understanding that the object shouldn't be actually instantiated? Is it possible this is because it's an actual object and not an interface?
I've tried configuring a la Baeldung, although the article talks about running as @SpringBootTest rather than a stripped back MVC test. Adding that config as context configuration causes all tests to start returning nulls for redirectedUrls, views, etc. as if it's not being set up correctly - which it probably isn't.
Is there something very obvious that I'm missing as to how my tests could sometimes seemingly be using a non-mocked object?
EDIT:
The plot thickens! Just for kicks, I decided to add a sysout to the start of a few of the controller methods which print out the value of the bean, hoping to get a memory address.
For every test which passes, it prints scopedBean bean.
For the tests which fail, it prints an actual toString a la MyScopedBean(valueA=null, valueB=null, valueC=null) - which seems...wrong. Call me crazy, but that sounds like it's actually creating an object there?
EDIT 2:
我已經向 Spring 團隊提出了這個問題——乍一看它可能與這個問題有關,但是洗掉@SessionScope并不能解決問題。添加 mockito-inline 也不會。交換到@SpyBean會導致稍微更加一致 - 但doReturns 似乎仍然被忽略。
uj5u.com熱心網友回復:
所以解決方案是添加mockito-inline靜態方法——但不幸的是,我在控制器的下方也犯了一個錯誤,這是真正的罪魁禍首。
任何創建 as as 的東西@MockBean仍然可以被覆寫 - 所以在我的一種方法中,我已經完成了:
scopedBean = new ScopedBean();
...“重置”它。在實踐中作業正常 - 除非您進行測驗,這意味著模擬被替換為真實版本的 bean,并且因為測驗重用相同的背景關系,所以“模擬”將無用。
相反,我創建了一個方法來重置它而不重新實體化。mockito-inline不再需要。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/456729.html
