【问题标题】:How can I write unit tests for private methods of service and for public methods with private inside?如何为私有服务方法和内部私有的公共方法编写单元测试?
【发布时间】:2018-07-09 10:10:06
【问题描述】:

我有服务:

@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)。如果有,怎么做?

【问题讨论】:

  • 你不应该模拟/测试私有方法。但是,您可以通过您的公共方法测试私有方法。在 validateCashier 方法中,您可以控制用户对象,只需在测试方法上使用 @Test(expected=AuthException.class) 或使用 @Rule public final ExpectedException exception = ExpectedException.none(); 存根 userRepository 返回 null 并期望 AuthException 请查看 link 了解更多详细信息

标签: java spring unit-testing mocking mockito


【解决方案1】:

UnitTests 测试代码,它们验证公共可观察行为,即返回值与依赖关系的通信

private 方法是您间接测试的实现细节(如JWo 所述)

原因是您以后可以更改您的实现细节(重构它们)而不破坏您现有的任何单元测试。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-25
      • 2023-03-19
      • 2017-03-25
      • 2014-08-10
      • 1970-01-01
      相关资源
      最近更新 更多