P. Aiello
P. Aiello

Reputation: 127

Mockito verify invocation error

I would have a problem with the junit tests with mockito. when I try to verify a service I get the error: "Actual invocation has different arguments"

Model:

@Entity
@Table(name = "projects")
public class Project {

    @Id
    @GeneratedValue(generator="increment")
    @GenericGenerator(name="increment", strategy = "increment")
    @Column(name = "id_project")
    private Long id;

    @Column(name = "project_name")
    private String name;

    @JsonInclude(value = Include.NON_NULL)
    @Column(name = "project_language")  
    private String language;

    @Temporal(TemporalType.DATE)
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
    @Column(name = "start_date")
    private Date start_date;

    @Temporal(TemporalType.DATE)
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
    @Column(name = "end_date")
    private Date end_date;

    @Transient
    @JsonIgnoreProperties
    private Long id_user;

    @ManyToOne
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumn(name = "id_content_manager")
    private User contentManager;

    @Transient
    private Long id_license;

    @OneToOne
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumn(name = "id_license")
    private License license;

    @OneToMany
    @LazyCollection(LazyCollectionOption.FALSE)
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinTable(name = "team", joinColumns = { @JoinColumn(name = "id_project") }, inverseJoinColumns = { @JoinColumn(name = "id_user") })
    private List<User> team;

    @OneToOne
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumn(name = "id_policy")
    private ProjectPolicy policy;

    @OneToMany
    @LazyCollection(LazyCollectionOption.FALSE)
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinTable(name = "project2tag", joinColumns = { @JoinColumn(name = "id_project") }, inverseJoinColumns = { @JoinColumn(name = "id_tag") })
    private List<Tag> tags = new ArrayList<Tag>();
...

Controller:

@RequestMapping(value = "/", method = RequestMethod.PUT, consumes = "application/json" , produces = "application/json")
    public @ResponseBody ResponseEntity<BaseModel> edit( @RequestHeader(value="Authorization") String token, @RequestBody Project project, Locale locale) throws ParseException{
        if(!SecurityUtil.validateToken(token)) {
            return new ResponseEntity<BaseModel>(new BaseModel("error", MessageHandler.returnMessage("invalid_token", locale)), HttpStatus.UNAUTHORIZED);
        }
        if(project.getId() == null ) {
            return new ResponseEntity<BaseModel>(new BaseModel("error", "Bad request"), HttpStatus.BAD_REQUEST);
        }

        Project projecttmp = projectDao.findById(project.getId());
        if( projecttmp != null) {
            project.setContentManager(projecttmp.getContentManager());
            project.setLicense(projecttmp.getLicense());
            project.setPolicy(projecttmp.getPolicy());
            project.setTags(projecttmp.getTags());
            project.setTeam(projecttmp.getTeam());
            projectDao.editProject(project);
            return new ResponseEntity<BaseModel>(new BaseModel("ok", "ok"), HttpStatus.OK);
        }

        return new ResponseEntity<BaseModel>(new BaseModel("error", MessageHandler.returnMessage("internal_error", locale)), HttpStatus.INTERNAL_SERVER_ERROR);
    }

and the test with failure:

@Test
    public void updateProject() throws Exception{
        Project project = new Project();
        project.setId(new Long(22));

        when(projectService.findById(anyLong())).thenReturn(project);

        String json = mapper.writeValueAsString(project);

        logger.info(json);

        doNothing().when(projectService).editProject(any(Project.class));

        mockMvc.perform(put("/project/")
                .header("Authorization", TOKEN)
                .accept(MediaType.APPLICATION_JSON)
                .content(json)
                .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andDo(MockMvcResultHandlers.print());

        verify(projectService, times(1)).findById(eq(project.getId()));
        verify(projectService, times(1)).editProject(eq(project));
    }

When i can try to run the test the result is "Actual invocation has different arguments" someone who can help me?

Upvotes: 1

Views: 805

Answers (1)

Nikolai  Shevchenko
Nikolai Shevchenko

Reputation: 7521

Mockito.eq() compares using .equals() method. You should override this method (and hashCode as well) in Project class, and make comparison by id. For example:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Project project = (Project) o;

    return getId() != null ? getId().equals(project.getId()) : project.getId() == null;
}

@Override
public int hashCode() {
    return getId() != null ? getId().hashCode() : 0;
}

Upvotes: 2

Related Questions