Java 如何在单元测试中模拟 JPA 存储库的保存方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/51247796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to mock JPA repository's save method in unit tests
提问by ip696
For example, I have this method in UserService:
例如,我在 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;
}
How can I create unit test for this method? I tried next:
如何为此方法创建单元测试?我接下来尝试:
@Test
public void createUser() {
UserDto userDtoRequest = new UserDto();
userDtoRequest.setLogin("Alex");
userDtoRequest.setPassword("123");
UserDto found = userService.create(userDtoRequest);
assertThat(found.getAuthToken()).isNotEmpty();
}
I have next logic:
我有下一个逻辑:
- Test start
User dbUser = userRepository.findOne(userDto.getId());
dbUser = NULLif (dbUser != null
) andif (oneByLogin != null)
skip- create new user and set data
User savedUser = userRepository.save(newUser);
savedUser = NULL
- 测试开始
User dbUser = userRepository.findOne(userDto.getId());
数据库用户 = NULLif (dbUser != null
) 并if (oneByLogin != null)
跳过- 创建新用户并设置数据
User savedUser = userRepository.save(newUser);
已保存用户 = NULL
On this step, I have a problem because I cannot mock userRepository.save(newUser)
.
在这一步中,我遇到了问题,因为我无法模拟userRepository.save(newUser)
.
newUser create inside the method. and test fail.
savedUser.getAuthToken() - savedUser == NULL
savedUser.getAuthToken() - savedUser == NULL
I can rewrite:
我可以重写:
userRepository.save(newUser);
userDto.setAuthToken(newUser.getAuthToken());
log.info("User {0} created", newUser.getLogin());
return userDto;
but what if I want to use the returned object savedUser
?
但是如果我想使用返回的对象savedUser
呢?
回答by rieckpil
You can do the following:
您可以执行以下操作:
@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
}
}
with this approach you just have to make sure your mockedUserRepository
gets injected into your class under test (e.g. in the constructor).
使用这种方法,你只需要确保你mockedUserRepository
被注入到你的被测类中(例如在构造函数中)。
回答by codeLover
You need to write multiple test cases in order to test different scenarios.
您需要编写多个测试用例来测试不同的场景。
Scenario 1: when findOnereturns a not null object:
场景一:当findOne返回一个非空对象时:
@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);
}
Scenario 2: when findOneByLoginreturns a null object:
场景二:当findOneByLogin返回一个空对象时:
@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);
}
Scenario 2: when saveis done:
场景2:保存完成后:
@Test
@测试
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());
}
回答by spajdo
You need to do this.
你需要这样做。
when(userRepository.save(Mockito.any(User.class)))
.thenAnswer(i -> i.getArguments()[0]);
And now you can obtain user which you pass as argument.
现在您可以获得作为参数传递的用户。