我正在尝试为POST REST端点编写单元测试。我需要使用嘲笑来模拟在上述端点中使用的服务方法。使用模拟mvc触发端点。
我在端点中模拟使用userService.saveUser(user)并返回一个整数作为创建的userId。但似乎该模拟总是返回0而不是7777(已禁用userId)。 对于“验证”,它说“参数不同!”它将传递给端点和我定义的模拟中的userService(user)。
Mockito验证错误:
Argument(s) are different! Wanted:
userService.saveUser(
com.foo.dto.User@741f8dbe
);
-> at com.foo.controller.UserControllerTest.saveUser(UserControllerTest.java:104)
Actual invocation has different arguments:
userService.saveUser(
com.foo.dto.User@212dfd39
);
-> at com.foo.controller.UserController.saveUser(UserController.java:45)
Comparison Failure: <Click to see difference>
我想这是因为@RequestBody注释创建了User的全新对象。 这会导致无法使用“ userService”模拟的问题。(如果我输入错误,请纠正我)
也许我需要做一些工作来触发端点,并将“用户”对象传递给Test类中定义的“ userService”,并跳过@RequestBody注释。
有人可以引导我解决这个问题吗?任何帮助将不胜感激。
端点:
@PostMapping("/users")
public ResponseEntity<String> saveUser(@RequestBody User user){
int userId = userService.saveUser(user);
return new ResponseEntity<>("User created. Id: "+ userId, HttpStatus.CREATED);
}
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
public class UserControllerTest {
@InjectMocks
private UserController userController;
@Mock
private UserService userService;
private ObjectMapper mapper;
private MockMvc mockMvc;
private Integer userId = 7777;
@Before
public void setUp() throws Exception{
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
mapper = new ObjectMapper();
user = new User();
user.setName("DummyUser");
}
@Test
public void saveUser(){
when(userService.saveUser(user)).thenReturn(userId);
this.mockMvc.perform(post("/users")
.accept(MediaType.TEXT_PLAIN)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsString(user)))
.andExpect(status().isCreated())
.andExpect(content()
.contentTypeCompatibleWith(MediaType.TEXT_PLAIN))
.andExpect(content().string("User created. Id: "+userId));
verify(userService).saveUser(user);
}
}
答案 0 :(得分:1)
我认为原因是您所说的。您可以做的是使用匹配器传递给您的模拟,因此只要接收到特定类型的对象(而不是特定对象:
),它将返回您想要的内容import static org.mockito.ArgumentMatchers.any;
...
when(userService.saveUser(any(User.class))).thenReturn(userId);
该模拟程序(在您使用时使用)将仅在执行when
时接收要传递的特定对象作为调用的参数时才返回所需的内容。从异常中可以看出,该模拟程序期望接收到一个引用为com.foo.dto.User@741f8dbe
的对象(这是您在setUp方法中创建的对象),但是它正在接收com.foo.dto.User@212dfd39
,该对象为杰克逊反序列化其余呼叫的主体时生成的一个。