package com.wesabe.grendel.resources.tests; import static org.fest.assertions.Assertions.*; import static org.mockito.Mockito.*; import java.net.URI; import java.util.List; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; import org.junit.Before; import org.junit.Test; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import com.google.common.collect.ImmutableList; import com.wesabe.grendel.entities.User; import com.wesabe.grendel.entities.dao.UserDAO; import com.wesabe.grendel.openpgp.KeySet; import com.wesabe.grendel.openpgp.KeySetGenerator; import com.wesabe.grendel.representations.CreateUserRepresentation; import com.wesabe.grendel.representations.ValidationException; import com.wesabe.grendel.representations.UserListRepresentation.UserListItem; import com.wesabe.grendel.resources.UsersResource; @RunWith(Enclosed.class) public class UsersResourceTest { private static abstract class Context { protected KeySetGenerator generator; protected UserDAO userDAO; protected UsersResource resource; public void setup() throws Exception { this.generator = mock(KeySetGenerator.class); this.userDAO = mock(UserDAO.class); this.resource = new UsersResource(generator, userDAO); } } public static class Listing_All_Users extends Context { private User user; private UriInfo uriInfo; @Before @Override public void setup() throws Exception { super.setup(); this.uriInfo = mock(UriInfo.class); when(uriInfo.getBaseUriBuilder()).thenAnswer(new Answer<UriBuilder>() { @Override public UriBuilder answer(InvocationOnMock invocation) throws Throwable { return UriBuilder.fromUri("http://example.com"); } }); this.user = mock(User.class); when(user.getId()).thenReturn("mrpeeper"); when(user.toString()).thenReturn("mrpeeper"); when(userDAO.findAll()).thenReturn(ImmutableList.of(user)); } @Test public void itFindsAllUsers() throws Exception { resource.list(uriInfo); verify(userDAO).findAll(); } @Test public void itReturnsAListOfAllUsers() throws Exception { final List<UserListItem> list = resource.list(uriInfo).getUsers(); assertThat(list).hasSize(1); assertThat(list.get(0).getId()).isEqualTo("mrpeeper"); assertThat(list.get(0).getUri()).isEqualTo("http://example.com/users/mrpeeper"); } } public static class Creating_A_New_User extends Context { private UriInfo uriInfo; private CreateUserRepresentation request; private KeySet keySet; private User user; private UriBuilder uriBuilder; @Before @Override public void setup() throws Exception { super.setup(); this.uriInfo = mock(UriInfo.class); this.request = mock(CreateUserRepresentation.class); when(request.getId()).thenReturn("username"); when(request.getPassword()).thenReturn("password".toCharArray()); this.keySet = mock(KeySet.class); when(keySet.getEncoded()).thenReturn(new byte[] { 1, 2, 3 }); when(keySet.getUserID()).thenReturn("username"); this.user = mock(User.class); when(generator.generate(Mockito.anyString(), Mockito.any(char[].class))).thenReturn(keySet); when(userDAO.contains(Mockito.anyString())).thenReturn(false); when(userDAO.saveOrUpdate(Mockito.any(User.class))).thenReturn(user); this.uriBuilder = mock(UriBuilder.class); when(uriBuilder.path(Mockito.any(Class.class))).thenReturn(uriBuilder); when(uriBuilder.build(Mockito.anyVararg())).thenReturn(URI.create("http://example.com/woot/")); when(uriInfo.getBaseUriBuilder()).thenReturn(uriBuilder); } @Test public void itValidatesTheRequest() throws Exception { resource.create(uriInfo, request); verify(request).validate(); } @Test public void itSanitizesTheRequest() throws Exception { resource.create(uriInfo, request); verify(request).sanitize(); } @Test public void itChecksToSeeIfTheUsernameIsTaken() throws Exception { resource.create(uriInfo, request); verify(userDAO).contains("username"); } @Test public void itGeneratesAKeySet() throws Exception { resource.create(uriInfo, request); final ArgumentCaptor<char[]> password = ArgumentCaptor.forClass(char[].class); verify(generator).generate(Mockito.eq("username"), password.capture()); assertThat(password.getValue()).isEqualTo("password".toCharArray()); } @Test public void itCreatesANewUser() throws Exception { resource.create(uriInfo, request); final ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class); verify(userDAO).saveOrUpdate(userCaptor.capture()); assertThat(userCaptor.getValue().getKeySet()).isSameAs(keySet); } @Test public void itReturnsA201CreatedWithTheUsersLocation() throws Exception { final Response r = resource.create(uriInfo, request); assertThat(r.getStatus()).isEqualTo(Response.Status.CREATED.getStatusCode()); assertThat(r.getMetadata().getFirst("Location")).isEqualTo(URI.create("http://example.com/woot/")); } } public static class Creating_A_New_User_With_A_Conflicting_Username extends Context { private UriInfo uriInfo; private CreateUserRepresentation request; @Before @Override public void setup() throws Exception { super.setup(); this.uriInfo = mock(UriInfo.class); this.request = mock(CreateUserRepresentation.class); when(request.getId()).thenReturn("username"); when(request.getPassword()).thenReturn("password".toCharArray()); when(userDAO.contains(Mockito.anyString())).thenReturn(true); } @Test public void itThrowsAValidationException() throws Exception { try { resource.create(uriInfo, request); } catch (ValidationException e) { final String msg = (String) e.getResponse().getEntity(); assertThat(msg).isEqualTo( "Grendel was unable to process your request for the following reason(s):\n" + "\n" + "* username is already taken\n" ); } } } }