package de.asideas.crowdsource.security; import com.fasterxml.jackson.databind.ObjectMapper; import de.asideas.crowdsource.domain.model.UserEntity; import de.asideas.crowdsource.repository.UserRepository; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.core.io.ClassPathResource; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.test.util.ReflectionTestUtils; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class DefaultUserServiceTest { @InjectMocks private DefaultUsersService defaultUserService = new DefaultUsersService(); @Mock private UserRepository userRepository; @Mock private PasswordEncoder passwordEncoder; @Mock private ClassPathResource mockedInputSource; private ObjectMapper objectMapper = new ObjectMapper(); @Before public void init() { reset(userRepository, passwordEncoder, mockedInputSource); ReflectionTestUtils.setField(defaultUserService, "objectMapper", objectMapper); } @Test public void shouldChangeNothingIfFileNotFound() { prepareResourceMock(false, true); defaultUserService.loadDefaultUsers(); verify(userRepository, never()).save(any(UserEntity.class)); } @Test public void shouldChangeNothingIfFileIsNotReadable() { prepareResourceMock(true, false); defaultUserService.loadDefaultUsers(); verify(userRepository, never()).save(any(UserEntity.class)); } @Test public void shouldChangeNothingIfEmptyArray() throws IOException { prepareResourceMock("[]"); defaultUserService.loadDefaultUsers(); verify(userRepository, never()).findByEmail(anyString()); verify(userRepository, never()).save(any(UserEntity.class)); } @Test(expected = IllegalStateException.class) public void shouldChangeNothingIfEmptyFile() throws IOException { prepareResourceMock(""); defaultUserService.loadDefaultUsers(); verify(userRepository, never()).findByEmail(anyString()); verify(userRepository, never()).save(any(UserEntity.class)); } @Test public void shouldCreateUsersIfNotExists() throws IOException { prepareResourceMock("[{\"email\": \"foo@bar.de\", \"password\":\"aPw\", \"activated\":\"true\",\"roles\": [\"ROLE_FOO\"]}]"); final UserEntity expUser = createUserEntity("foo@bar.de", "anEncryptedPw", true, Collections.singletonList("ROLE_FOO")); when(passwordEncoder.encode(eq("aPw"))).thenReturn("anEncryptedPw"); defaultUserService.loadDefaultUsers(); final ArgumentCaptor<UserEntity> userCaptor = ArgumentCaptor.forClass(UserEntity.class); verify(userRepository, times(1)).save(userCaptor.capture()); assertSameContent(userCaptor.getValue(), expUser); } @Test public void shouldCreateMultipleUsers() throws IOException { prepareResourceMock("[{\"email\": \"foo@bar.de\", \"password\":\"aPw\", \"activated\":\"true\",\"roles\": [\"ROLE_FOO\"]}, " + "{\"email\": \"foo2@bar.de\", \"password\":\"aPw\", \"activated\":\"false\",\"roles\": [\"ROLE_FOO_2\"]}]"); when(passwordEncoder.encode(eq("aPw"))).thenReturn("anEncryptedPw").thenReturn("anEncryptedPw2"); defaultUserService.loadDefaultUsers(); final UserEntity user1 = createUserEntity("foo@bar.de", "anEncryptedPw", true, Collections.singletonList("ROLE_FOO")); final UserEntity user2 = createUserEntity("foo2@bar.de", "anEncryptedPw2", false, Collections.singletonList("ROLE_FOO_2")); ArgumentCaptor<UserEntity> captorUser = ArgumentCaptor.forClass(UserEntity.class); verify(userRepository, times(2)).save(captorUser.capture()); assertSameContent(captorUser.getAllValues().get(0), user1 ); assertSameContent(captorUser.getAllValues().get(1), user2 ); } @Test public void shouldUpdateExistingUsers() throws IOException { prepareResourceMock("[{\"email\": \"foo@bar.de\", \"password\":\"aPw\", \"activated\":\"true\",\"roles\": [\"ROLE_FOO\", \"ROLE_FOO_2\"]}]"); when(userRepository.findByEmail(eq("foo@bar.de"))).thenReturn(createUserEntity("foo@bar.de", "oldEncryptedPw", false, Collections.singletonList("ROLE_FOO"))); when(passwordEncoder.encode(eq("aPw"))).thenReturn("anEncryptedPw"); defaultUserService.loadDefaultUsers(); final UserEntity expUser = createUserEntity("foo@bar.de", "anEncryptedPw", true, Arrays.asList("ROLE_FOO", "ROLE_FOO_2")); final ArgumentCaptor<UserEntity> userCaptor = ArgumentCaptor.forClass(UserEntity.class); verify(userRepository, times(1)).save(userCaptor.capture()); assertSameContent(userCaptor.getValue(), expUser); } private UserEntity createUserEntity(String email, String password, boolean active, List<String> roles) { UserEntity entity = new UserEntity(); entity.setEmail(email); entity.setPassword(password); entity.setActivated(active); entity.setRoles(new ArrayList<>(roles)); return entity; } private void prepareResourceMock(boolean exists, boolean readable) { when(mockedInputSource.exists()).thenReturn(exists); when(mockedInputSource.isReadable()).thenReturn(readable); } private void prepareResourceMock(String fileContent) throws IOException { prepareResourceMock(true, true); when(mockedInputSource.getInputStream()).thenReturn(new ByteArrayInputStream(fileContent.getBytes("UTF-8"))); } private void assertSameContent(UserEntity user1, UserEntity user2){ assertThat(user1.getRoles(), is(user2.getRoles())); assertThat(user1.getEmail(), is(user2.getEmail())); assertThat(user1.getPassword(), is(user2.getPassword())); assertThat(user1.isActivated(), is(user2.isActivated())); } }