【问题标题】:Test JPA repository for void functions and updates and deletes测试 JPA 存储库的 void 函数以及更新和删除
【发布时间】:2020-10-21 06:19:46
【问题描述】:

我正在为一个 crud 应用程序编写测试。我需要为 Delete 和 Update 语句测试服务和存储库。由于它们不会返回数据,我将如何模拟存储库以进行删除和更新?

例如:

@Override
public void makeUserActive(long userId) {
   try {
       Optional<UserEntity> userEntityList = usersJpaRepository.findById(userId);
       UserEntity userEntity = userEntityList.get();
       userEntity.setIsActive(1);
       usersJpaRepository.save(userEntity);
   } catch (Exception e) {
       logger.error("Cant make active user", e);
   }
 }

我如何测试模拟此存储库的服务以及存储库本身,因为它不会返回值

【问题讨论】:

    标签: java spring-boot jpa testing junit


    【解决方案1】:

    问题是您要测试的事物是什么? 如果您想测试您的存储库,您可以使用 Springs @DataJpaTest 来实现。见Integration Testing With @DataJpaTest

    如果您想测试 makeUserActive-Method 中的逻辑,您必须确保模拟您的存储库。

    假设包含您的makeUserActive-Method 的服务看起来像这样:

    public class UserService{
    
        private final UsersJpaRepository usersJpaRepository;
    
        public UserService(UsersJpaRepository usersJpaRepository) {
            this.usersJpaRepository = usersJpaRepository;
        }
    
        public void makeUserActive(long userId){
            // your code from your question
    
        }
    }
    

    你可以这样写你的单元测试:

    @Test
    void makeUserActiveTest(){
        UsersJpaRepository repository = new InMemoryUsersJpaRepository();
        UserEntity user = new UserEntity();
        user = repository.save(user);
    
        UserService service = new UserService(repository);
    
        service.makeUserActive(user.getId());
    
        Optional<UserEntity> activatedUser = repository.findById(user.getId());
    
        assertTrue(activatedUser.isPresent());
        assertEquals(1, activatedUser.get().isActive());
    }
    

    InMemoryUsersJpaRepository 是一个自写的 Mock,它将所有数据存储在内部 Map 中。代码可能如下所示:

    public class InMemoryUsersJpaRepository extends UsersJpaRepository {
    
        private Map<Long, UserEntity> users = new HashMap<>();
        private Long idCounter = 1L;
    
        @Override
        public UserEntity save(UserEntity user) {
            if(user.getId() == null){
                user.setId(idCounter);
                idCounter++;
            }
    
            users.put(user.getId(), user);
    
            return user;
        }
    
        @Override
        public Optional<UserEntity> findById(long userId) {
            return Optional.of(users.get(userId));
        }
    }
    

    这样您将测试您的 makeUserActive-Method 的逻辑,该方法目前只是在您的 UserEntity 上设置 isActivated 标志。


    另外,我想提醒您有关 Mensur Qulami 的 answer。 他回答中的代码将导致通过测试,但我很确定它不会测试您想要测试的东西。
    您应该始终测试您的方法的预期和可观察行为。 在您的情况下,这将是应为 1 的 isActivated 标志。
    您的makeUserActive-Method 调用UsersJpaRepositoryfindByIdsave 方法这一事实仅仅是实现细节,对这些方法的测试通常会导致脆弱的测试。

    【讨论】:

      【解决方案2】:

      对于返回void 的方法,您可以简单地验证它们是否已被调用。这是一个示例,它同时模拟了一个对象返回方法和void 返回方法。

      @ExtendWith(MockitoExtension.class)
      class ServiceTest {
      
          @Mock
          private Repository repository;
          @InjectMocks
          private Service service; // assume that this is your class
      
          @Test
          void testMakeUserActive() {
              // given:
              final UserEntity userEntity = new UserEntity();
              // mocks:
              when(repository.findById(1)).thenReturn(Optional.of(userEntity));
      
              // when:
              service.makeUserActive(1);
      
              // then:
              verify(repository).findById(1);
              verify(repository).save(userEntity); 
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-11-13
        • 2019-05-18
        • 2015-05-24
        • 2020-02-05
        • 2014-08-13
        • 1970-01-01
        • 1970-01-01
        • 2018-07-30
        • 1970-01-01
        相关资源
        最近更新 更多