首页 > 解决方案 > Long 和 Lombok 的 Mockito 问题

问题描述

如何为以下代码编写 mockito,我经历了:https ://examples.javacodegeeks.com/core-java/junit/junit-mockito-when-thenreturn-example/

代码:

@Override
public void saveEmployee(EmployeeDto dto) {
    Department department = getByDepartmentId(dto.getDepartmentId());
    RoleType roleType = getByRoleTypeId(dto.getRoleTypeId());

    Employee departmentMember = convertToEntity(dto, department, roleType);

    try {
        departmentMemberRepository.save(departmentMember);
    } catch (DataIntegrityViolationException e) {
        throw new PCDataIntegrityViolationException("error");
    } catch (Exception ex) {
        throw new InternalServerException(HttpStatus.INTERNAL_SERVER_ERROR, "error", ex);
    }
}

private Employee convertToEntity(EmployeeDto dto, Department department, RoleType roleType) {
    return Employee.pmBuilder()
            .memberEmployeeId(dto.getMemberEmployeeId())
            .memberEmployeeName(dto.getMemberEmployeeName())
            .createUser(dto.getCreateUser())
            .lastUpdateUser(dto.getLastUpdateUser())
            .status(StatusEnum.get(dto.getStatus()))
            .department(department)
            .roleType(roleType)
            .build();
}

private Department getByDepartmentId(Long departmentId) {
    Optional<Department> optDepartment = departmentRepository.findById(departmentId);
    if(!optDepartment.isPresent()) {
        throw new ResourceNotFoundException("Error");
    }
    return optDepartment.get();
}

private RoleType getByRoleTypeId(Integer roleTypeId) {
    RoleType roleType = roleTypeRepository.findByRoleTypeId(roleTypeId);
    if(roleType == null) {
        throw new ResourceNotFoundException("error");
    }
    return roleType;
}

我已经写了测试课,唯一的问题是

@RunWith(PowerMockRunner.class)
@PrepareForTest({AHUtils.class })
public class EmployeeServiceTest {
    @InjectMocks
    private EmployeeServiceimpl employeeServiceimpl;
    @Mock
    private Pageable pageable;
    @Mock
    private Page<Employee> employeePage;

    @Mock
    private EmployeeRepository employeeRepository;
    @Mock
    private DepartmentRepository departmentRepositoryMock;

    @Mock
    private Employee employee;
    @Mock
    private Optional<Employee> employeeOptional;
    @Mock
    private Department departmentMock;
    @Mock
    private Optional<Department> departmentOptionalMock;
    @Mock
    private EmployeeDto employeeDto;
    @Mock
    private Sort sortMock;
    @Mock
    private Exception ex;
    @Mock
    private Environment env;

    @Test(expected = ResourceNotFoundException.class)
    public void test_RoleTypeNotPresent() {
        when(departmentOptionalMock.get()).thenReturn(departmentMock);
        when(departmentOptionalMock.isPresent()).thenReturn(true);
        when(departmentRepositoryMock.findById(null)).thenReturn(departmentOptionalMock);
        doThrow(new ResourceNotFoundException("error")).when(employeeRepository).save(any());
        when(employeeDto.getDepartmentId()).thenReturn(null);
        employeeServiceimpl.saveEmployee(employeeDto);
    }
}

什么时候Optional<Department> optDepartment = departmentRepository.findById(departmentId);,我想在其中有价值,以便我继续,这个测试用例进入 if 块。

标签: mockitopowermockito

解决方案


如果您DepartmentRepository没有被注入到您的体内,请EmployeeServiceimpl确保以下事项(基于javadoc of InjectMocks):

  • 如果您至少有一个带参数的构造函数:(
    在这种情况下,Mockito 使用构造函数注入)

    所有应该注入的模拟必须是具有最多参数的构造函数的参数。

    另请注意,如果存在非无参数构造函数,则 mockito 不会考虑其他注入方法。

  • 第二种情况是你有你想要模拟的东西的 setter 方法
    (在这种情况下,Mockito 将使用 setter 注入)

  • 如果您只有一个无参数构造函数而没有设置器:(
    在这种情况下,Mockito 将使用字段注入)

    所有带有注释的模拟必须与您的类 @Mock中的字段共享相同的名称。EmployeeServiceimpl


Overmocking通常是指您生成了太多模拟的事实,即使对于不需要模拟的东西也是如此。

您可以将前 3 行更改为以下示例所示的内容。

请注意,我.findById(null).findById(anyLong()). 我不确定getDepartmentId()实际返回的是什么,对于一个原始的 long 你必须anyLong()用作模拟将默认返回 0 (而不是 null )。

但是,在下面的示例中,我将其设置为departmentId1L因此无论如何它都应该匹配。

@RunWith(PowerMockRunner.class)
@PrepareForTest({AHUtils.class })
public class EmployeeServiceTest {

    @InjectMocks
    private EmployeeServiceimpl employeeServiceimpl;

    @Mock
    private DepartmentRepository departmentRepositoryMock;

    @Test(expected = ResourceNotFoundException.class)
    public void test_RoleTypeNotPresent() {

        Department department = new Department();
        department.setDepartmentId(1L);

        // only if you can't simply create that object, use the mock
        // Department department = Mockito.mock(Department.class);

        when(departmentRepositoryMock.findById(anyLong())).thenReturn(Optional.of(department));

        // ... the rest of the example does not match with the code you posted ...

        employeeServiceimpl.saveEmployee(employeeDto);
    }
}

请注意,测试的剩余部分,

doThrow(new ResourceNotFoundException("error")).when(employeeRepository).save(any());
when(employeeDto.getDepartmentId()).thenReturn(null);

与您发布的代码并不真正匹配。相反,您应该在roleTypeRepository.

我也不确定应该在什么时候抛出异常,因为似乎没有与employeeRepository.


推荐阅读