需要在POST端点中模拟服务方法,以滑动@RequestBody注释

问题描述 投票:0回答:1

我正在尝试为POST REST端点编写单元测试。我需要使用mockito模拟在上面的端点中使用的服务方法。使用模拟mvc来触发端点。

我正在端点中使用userService.saveUser(user),并返回一个整数作为创建的userId。但似乎模拟总是返回0而不是7777(userId deifined)。对于“验证”,它说“参数不同!”它传递给端点中的userService(用户)和我定义的模拟。

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”模拟的问题。(纠正我,如果我错了)

可能是我必须做一个工作来触发端点并将“user”对象传递给“userService”,因为它在Test类中定义并跳过@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);
    }

}
spring-boot junit mockito mockmvc
1个回答
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,这是Jackson在反序列化时生成的其余的身体呼唤。

© www.soinside.com 2019 - 2024. All rights reserved.