Mockito测试期间对象参考的变化

时间:2015-03-12 16:46:04

标签: spring unit-testing mockito

我刚刚开始与Mockito合作,并且遇到其中一个测试失败的问题,但实际代码在实时环境中正常运行。正在测试的控制器是:

@Controller
@RequestMapping("/notes")
public class NotesController {

private NoteRepository noteRepository;
private MyUserRepository userRepository;

@RequestMapping(value = "/add", method = POST)
public String postNote(@Valid Note note, BindingResult errors, Principal principal){
    String username = principal.getName();
    MyUser user = userRepository.findUserByUsername(username);
    note.setMyUser(user);
    note.setTime(new Date());
    noteRepository.save(note);
    return "redirect:/notes";    }
}

测试在这里:

@Test
public void testShouldAddValidNote() throws Exception {
    MyUser testing = new MyUser();
    Note note = new Note();
    NoteRepository noteRepository = mock(NoteRepository.class);
    when(noteRepository.save(note)).thenReturn(note);

    MyUserRepository userRepository = mock(MyUserRepository.class);
    when(userRepository.findUserByUsername("testing")).thenReturn(testing);

    Principal mockPrincipal = mock(Principal.class);
    when(mockPrincipal.getName()).thenReturn("testing");


    NoteController controller = new NoteController(noteRepository);
    controller.setMyUserRepository(userRepository);
    MockMvc mockMvc = standaloneSetup(controller).build();

    mockMvc.perform(post("/notes/add")
            .requestAttr("note", note)
            .principal(mockPrincipal))
            .andExpect(view().name("redirect:/notes"));

    verify(noteRepository,times(1)).save(note);
    verify(note,times(1)).setMyUser(testing);
    verify(note,times(1)).setTime((Date)anyObject());
    verify(userRepository,times(1)).findUserByUsername("testing");
    verify(mockPrincipal,times(1)).getName();
}

第一次验证测试失败,并显示以下消息:

Argument(s) are different! Wanted:
noteRepository.save(projectName.Note@5ae9);

Actual invocation has different arguments:
noteRepository.save(projectName.Note@c079ae45

显然传入方法的Note对象已经改变,但我认为使用.requestAttr(“note”,note)会传入引用,因此同一个对象应该在方法中(后来返回)。就像我说的那样,它在实时网络容器中运行得非常好,所以我对Mockito测试有什么问题呢?

1 个答案:

答案 0 :(得分:1)

这只是一个疯狂的猜测,这个代码所面临的问题是来自MockMvc / MockMvcRequestBuilders,其中Note在请求配置和实际请求之间以某种方式被序列化/反序列化?< / p>

请注意,note是一个真实的对象,因此调用verify(note)....将无效。

无论如何,我建议在这种情况下使用mockito captor和AssertJ的组合:

// if field instantiation if using the mockito runner / rule or MockitoAnnotations.initMocks(this)
@Captor ArgumentCaptor<Note> noteCaptor; 

// if created in the test method
ArgumentCaptor<Note> noteCaptor = ArgumentCaptor.forClass(Note.class);

// ...

verify(noteRepository,times(1)).save(noteCaptor.capture());
assertThat(noteCaptor.getValue().geMyUser()).isEqualTo(testing);
assertThat(noteCaptor.getValue().geTime()).isCloseTo(someDate);

注意我正在打电话