代码之家  ›  专栏  ›  技术社区  ›  ip696

单元测试中如何模拟JPA存储库的保存方法

  •  6
  • ip696  · 技术社区  · 6 年前

    例如,我在UserService中有这个方法:

      @Override
      @Transactional
      public UserDto create(UserDto userDto) {
    
        User dbUser = userRepository.findOne(userDto.getId());
    
        if (dbUser != null) {
          throw new AuthException(AuthException.ErrorCode.DUPLICATE_USER_EXCEPTION);
        }
    
        User oneByLogin = userRepository.findOneByLogin(userDto.getLogin());
        if (oneByLogin != null) {
          throw new AuthExceptionAuthException.ErrorCode.DUPLICATE_LOGIN_EXCEPTION);
        }
    
        User newUser = new User();
        newUser.setGuid(UUID.randomUUID().toString());
        newUser.setInsertDate(new Date());
        newUser.setFirstName(userDto.getFirstName());
        newUser.setLastName(userDto.getLastName());
        newUser.setLogin(userDto.getLogin());
        newUser.setPassword(userDto.getPassword());
        newUser.setAuthToken(TokenGenerator.nextToken());
        newUser.setAuthTokenCreatedDate(new Date());
    
        User savedUser = userRepository.save(newUser);
    
        userDto.setAuthToken(savedUser.getAuthToken());
        log.info("User {0} created", savedUser.getLogin());
        return userDto;
      }
    

    如何为该方法创建单元测试?我试了下一个:

      @Test
      public void createUser() {
    
        UserDto userDtoRequest = new UserDto();
        userDtoRequest.setLogin("Alex");
        userDtoRequest.setPassword("123");
    
        UserDto found = userService.create(userDtoRequest);
        assertThat(found.getAuthToken()).isNotEmpty();
    }
    

    我有下一个逻辑:

    1. 测试开始
    2. User dbUser = userRepository.findOne(userDto.getId()); dbUser=NULL
    3. if (dbUser != null )以及 if (oneByLogin != null) 跳过
    4. 创建新用户并设置数据
    5. User savedUser = userRepository.save(newUser); savedUser=空

    在这一步上,我有一个问题,因为我不能嘲笑 userRepository.save(newUser) .

    newUser create inside the method. and test fail.
    

    savedUser.getAuthToken()-savedUser==空

    我可以重写:

        userRepository.save(newUser);
        userDto.setAuthToken(newUser.getAuthToken());
        log.info("User {0} created", newUser.getLogin());
        return userDto;
    

    但是如果我想使用返回的对象 savedUser ?

    2 回复  |  直到 6 年前
        1
  •  5
  •   rieckpil    6 年前

    您可以执行以下操作:

    @RunWith(MockitoJUnitRunner.class)
    public class SimpleTest {
    
      @Mock
      private UserRepository mockedUserRepository;
    
      // .. your test setup
    
      @Test
      public void testYourMethod() {
    
         User userToReturnFromRepository = new User();
         userToReturnFromRepository.setAuthToken(YOUR_TOKEN);
         when(mockedUserRepository.save(any(UserDto.class)).thenReturn(userToReturnFromRepository);
    
         UserDto found = userService.create(userDtoRequest);
    
         // ... your asserts
    
      }
    
    }
    

    用这种方法你只需要确保 mockedUserRepository 被注入到正在测试的类中(例如在构造函数中)。

        2
  •  2
  •   spajdo    5 年前

    你必须这么做。

    when(userRepository.save(Mockito.any(User.class)))
                    .thenAnswer(i -> i.getArguments()[0]);
    

    现在可以获取作为参数传递的用户。

        3
  •  0
  •   codeLover Sumit Tyagi    6 年前

    为了测试不同的场景,您需要编写多个测试用例。

    场景1:何时 芬顿 返回非空对象:

    @Test(expected=AuthException.class)
    public void testCreateUserWhenAvailable()    {
         //Create one sample userDto object with test data
         when(mockedUserRepository.findOne(userDto.getId())).thenReturn(new User());
         userService.create(userDto);
    }
    

    场景2:何时 芬多内比洛金 返回空对象:

    @Test(expected=AuthException.class)
    public void testCreateUserWhenLoginAvailable()    {
         //Create one sample userDto object with test data
         when(mockedUserRepository.findOne(userDto.getId())).thenReturn(null);
         when(mockedUserRepository.findOneByLogin(userDto.getId())).thenReturn(new User());
    
         userService.create(userDto);
    }
    

    场景2:何时 节约 完成时间:

    @测试

    public void testCreateUserWhenSaved()    {
         //Create one sample userDto object with test data
         when(mockedUserRepository.findOne(userDto.getId())).thenReturn(null);
         when(mockedUserRepository.findOneByLogin(userDto.getId())).thenReturn(null);
    
         //Create sample User object and set all the properties
         User newUser=new User();
         when(mockedUserRepository.save(Mockito.any(User.class)).thenReturn(newUser);
         User returnedUser=userService.create(userDto);
         //You have two ways to test, you can either verify that save method was invoked by 
         //verify method
         verify(mockedUserRepository, times(1)).save(Mockito.any(User.class);
         //or by assertion statements, match the authToken in the returned object to be equal 
         //to the one set by you in the mocked object
         Assert.assertEquals(returnedUser.getAuthToken(),newUser.getAuthToken());
    }