如何为私有服务方法和内部私有方法编写单元测试?

时间:2018-07-09 10:10:06

标签: java spring unit-testing mocking mockito

我有服务

@Slf4j
@Service
public class CashierServiceDefault implements CashierService {

  private final UserRepository userRepository;

  @Autowired
  public CashierServiceDefault(UserRepository userRepository) {
    this.userRepository = userRepository;
  }

  @Override
  @Transactional
  public CashierDto login(CashierDto cashier) {

    User dbUser = userRepository.findOneByLoginAndPassword(cashier.getLogin(), cashier.getPassword());

    validateCashier(cashier.getLogin(), dbUser);

    User userWithToken = createAuthToken(dbUser);

    return domainUserToCashierDto(userWithToken, cashier);
  }

  private void validateCashier(String login, User dbUser) {

    if (dbUser == null) {
      log.error("Cashier: {} not found", login);
      throw new AuthException(AuthException.ErrorCode.USER_NOT_FOUND_EXCEPTION);
    }

    UserRole userRole = UserRole.valueOf(dbUser.getUserRole().getCode());
    if (userRole != UserRole.CASHIER) {
      log.error("User: {} has role: {}. expected: CASHIER ", login, userRole.toString());
      throw new AuthException(AuthException.ErrorCode.USER_ROLE_NOT_PERMISSION_EXCEPTION);
    }
  }

  private User createAuthToken(User user) {
    user.setAuthToken(TokenGenerator.nextToken());
    user.setAuthTokenCreatedDate(new Date());
    return userRepository.save(user);
  }

  private CashierDto domainUserToCashierDto(User user, CashierDto cashier) {
    //mapping user's fields to CashierDto,s fields
    return cashier;
  }

我要为此服务创建测试。我尝试过:

@RunWith(SpringRunner.class)
public class CashierServiceDefaultTest {

  @MockBean
  private UserRepository userRepository;

  private CashierService cashierService;

  @Before
  public void setUp() throws Exception {
    cashierService = new CashierServiceDefault(userRepository);
  }

  @Test
  public void login() {
    CashierDto cashierDto = new CashierDto();
    cashierDto.setLogin("Alex");
    cashierDto.setPassword("123");

    User user = new User();
    user.setLogin("Alex");
    user.setPassword("123");
    //and other test values

    when(userRepository.findOneByLoginAndPassword(cashierDto.getLogin(), cashierDto.getPassword())).thenReturn(user);

    CashierDto found = cashierService.login(cashierDto);
    assertThat(found.getAuthToken()).isEqualTo("123");
  }

我有问题:

1。如何在服务中测试private方法?,我需要测试它们吗?如果可以,怎么办?

2。我应该如何测试公共登录方法?我为存储库方法创建了一个存根:

when(userRepository.findOneByLoginAndPassword(cashierDto.getLogin(), cashierDto.getPassword())).thenReturn(user);

但是我应该对内部服务方法进行存根处理吗?(validateCashiercreateAuthTokendomainUserToCashierDto)。如果可以,怎么办?

2 个答案:

答案 0 :(得分:2)

UnitTest不会测试代码,它们会验证可观察的公共行为,即返回值与依赖项通信

{private方法是实施细节,您可以间接测试 (如JWo所述)

原因是您稍后可以在不破坏任何现有UnitTest的情况下更改实现细节(重构它们)。

答案 1 :(得分:0)

我不会直接对其进行测试。由于您将它们实现为对其他一些方法的帮助,因此您可以对其进行测试。通过测试所有公共方法,您也将测试私有方法。测试公共方法时,不要忘记为私有方法添加输入和输出。

另一种方法是将测试方法与生产代码放入同一包中。然后,您必须将私有方法设置为打包或受保护。