我正在Spring Boot gradle应用程序中测试REST API,使用@MockBean的模拟服务返回null。如果服务类中有一些自动装配的bean,则此模拟服务将返回null(我使用构造函数注入)。
这里是示例代码(未编译,仅用于理解)
@RestController
@RequestMapping("/xxx")
class TestController {
private RetriveDataService retriveDataService;
public TestControllerx(RetriveDataService retriveDataService) {
this.retriveDataService = retriveDataService;
}
@PostMapping(value = "/yyy")
public MyResponseModel myMethod(@RequestBody MyRequestModel model) {
return retriveDataService.retriveData(model);
}
}
@Service
class RetriveDataService {
private TokenService tokenService;
public RetriveDataService(TokenService tokenService) {
this.tokenService = tokenService;
}
public MyResponseModel retriveData(MyRequestModel model) {
String accessToken = tokenService.getToken().getAccessToken();
return retriveData(model, accessToken);
}
}
@RunWith(SpringRunner.class)
@WebMvcTest(TestController.class)
public class TestControllerTest {
@Autowired
private MockMvc mvc;
@Autowired
private ObjectMapper objectMapper;
@MockBean
private RetriveDataService retriveDataService;
@Test
public void testRetriveData() throws Exception {
mvc.perform(MockMvcRequestBuilders.post("/xxx/yyy").content(objectMapper.writeValueAsString(new MyRequestModel()))
.contentType(MediaType.APPLICATION_JSON_UTF8)).andDo(MockMvcResultHandlers.print())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8));
}
}
运行此测试时,我得到以下输出(如果我的服务不需要另一个bean,则得到预期的输出)
MockHttpServletResponse:
Status = 200
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
由于此响应,我在.andExpect(content()。contentType(MediaType.APPLICATION_JSON_UTF8));上遇到问题。当我检查响应主体时(因为主体也是一个空值)
重现该问题的示例项目为here
答案 0 :(得分:0)
检查存储库中已确认的假设,形成问题讨论中的讨论。
您指定对模拟的期望
MyModel requestMessage = new MyModel();
requestMessage.setMessage("Hello Request Post");
given(testService1.getMessage(requestMessage)).willReturn(responseMessage);
,但是在@WebMvcTest
中的控制器中接收到的消息不等于测试中指定的requestMessage。这是因为MyModel
类没有覆盖equals
方法。
在这种情况下,Mockito将使用其默认行为:
默认情况下,对于所有返回值的方法,模拟将酌情返回null,原始/原始包装器值或空集合。例如,对于int / Integer为0,对于boolean / Boolean为false。
您有两种方法可以解决此问题:
equals
(和hashCode
)。有关选项2的更多信息:
从技术上讲,您的期望等同于:
given(testService1.getMessage(ArgumentMatchers.eq(requestMessage)))
.willReturn(responseMessage);
您可以使用其他匹配器,甚至可以定义自己的匹配器。如果您无法修改自变量类型的代码(类型来自3方库等),这将很有用。
例如,您可以使用ArgumentMatchers.any(MyModel.class))