package com.porterhead.user;
import com.porterhead.exception.ValidationException;
import com.porterhead.user.api.ApiUser;
import com.porterhead.user.api.CreateUserRequest;
import com.porterhead.user.api.PasswordRequest;
import com.porterhead.user.api.UpdateUserRequest;
import com.porterhead.user.exception.AuthenticationException;
import com.porterhead.user.exception.DuplicateUserException;
import org.apache.commons.lang.RandomStringUtils;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.Validation;
import javax.validation.Validator;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;
@Transactional
public class UserServiceTest {
protected String emailAddress = "foobar@example.com";
protected String password = "password";
protected final String id = "12345";
protected UserRepository userRepository = Mockito.mock(UserRepository.class);
protected Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
protected DefaultTokenServices tokenServices;
protected UserServiceImpl userService;
protected TokenStore tokenStore;
@Before
public void setup() {
reset(userRepository);
tokenStore = mock(TokenStore.class);
tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore);
userService = new UserServiceImpl(userRepository, validator, new StandardPasswordEncoder());
final User user = new User(getApiUser(), password, Role.ROLE_USER);
Mockito.when(userRepository.save(Mockito.any(User.class))).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
return user;
}
});
}
@Test
public void createNewUserNonExisting() throws Exception {
mockEmailNotFound();
ApiUser user = createUserWithRandomUserName();
assertThat(user, is(not(Matchers.<Object>nullValue())));
verify(userRepository, times(1)).save(Mockito.any(User.class));
verify(userRepository, times(1)).findByEmailAddress(Mockito.any(String.class));
}
@Test(expected = DuplicateUserException.class)
public void duplicateUser() throws Exception {
mockEmailNotFound();
CreateUserRequest request = getDefaultCreateUserRequest();
userService.createUser(request);
when(userRepository.findByEmailAddress(Mockito.any(String.class))).thenReturn(new User());
//do again with same request
userService.createUser(request);
}
@Test(expected = ValidationException.class)
public void nullPasswordRequest() {
CreateUserRequest request = new CreateUserRequest();
request.setUser(getApiUser());
userService.createUser(request);
}
@Test(expected = ValidationException.class)
public void badNameRequest() {
CreateUserRequest request = new CreateUserRequest();
ApiUser user = getApiUser();
user.setFirstName(RandomStringUtils.randomAlphabetic(101));
request.setUser(user);
request.setPassword(new PasswordRequest());
userService.createUser(request);
}
@Test(expected = ValidationException.class)
public void nullEmailRequest() {
CreateUserRequest request = new CreateUserRequest();
ApiUser user = new ApiUser();
user.setFirstName("Foo");
user.setLastName("Bar");
request.setUser(user);
request.setPassword(new PasswordRequest("password"));
userService.createUser(request);
}
@Test
public void loadUserByUserName() {
User user = getDefaultUser();
when(userRepository.findByEmailAddress(emailAddress)).thenReturn(user);
assertThat(user, is(userService.loadUserByUsername(emailAddress)));
}
@Test(expected = UsernameNotFoundException.class)
public void userNotFoundByEmailAddress() {
User user = getDefaultUser();
when(userRepository.findByEmailAddress(createRandomEmailAddress())).thenReturn(user);
userService.loadUserByUsername(emailAddress);
}
private void mockEmailNotFound() {
Mockito.when(userRepository.findByEmailAddress(emailAddress)).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
return null;
}
});
}
private ApiUser createUserWithRandomUserName() {
CreateUserRequest request = getDefaultCreateUserRequest();
return userService.createUser(request);
}
private CreateUserRequest getDefaultCreateUserRequest() {
CreateUserRequest request = new CreateUserRequest();
request.setUser(getApiUser());
request.setPassword(new PasswordRequest(password));
return request;
}
private ApiUser getApiUser() {
ApiUser user = new ApiUser();
user.setEmailAddress(emailAddress);
return user;
}
private User getDefaultUser() {
User user = new User(getApiUser(), "password", Role.ROLE_USER);
return user;
}
protected String createRandomEmailAddress() {
return RandomStringUtils.randomAlphabetic(8) + "@example.com";
}
}