たとえば、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();
}
_
次のロジックがあります:
User dbUser = userRepository.findOne(userDto.getId());
dbUser = NULLif (dbUser != null
_)およびif (oneByLogin != null)
skipUser savedUser = userRepository.save(newUser);
savedUser = NULLこのステップでは、userRepository.save(newUser)
をモックできないため、問題があります。
_newUser create inside the method. and test fail.
_
savedUser.getAuthToken()-savedUser == NULL
書き直すことができます:
_ userRepository.save(newUser);
userDto.setAuthToken(newUser.getAuthToken());
log.info("User {0} created", newUser.getLogin());
return userDto;
_
しかし、返されたオブジェクトsavedUser
を使用したい場合はどうなりますか?
次のことができます。
@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
がテスト対象のクラス(コンストラクターなど)に挿入されることを確認する必要があります。
これを行う必要があります。
when(userRepository.save(Mockito.any(User.class)))
.thenAnswer(i -> i.getArguments()[0]);
これで、引数として渡すユーザーを取得できます。
異なるシナリオをテストするには、複数のテストケースを作成する必要があります。
シナリオ1:findOneがnull以外のオブジェクトを返す場合:
@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:findOneByLoginがnullオブジェクトを返す場合:
@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:saveが完了した場合:
@テスト
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());
}