From 5899e771b44f5e8521735c83deafdca6fd25febf Mon Sep 17 00:00:00 2001 From: DavidSholito Date: Fri, 26 Mar 2021 19:50:52 +0100 Subject: [PATCH] =?UTF-8?q?Inclusi=C3=B3n=20de=20los=20Test=20para=20la=20?= =?UTF-8?q?entidad=20Pet=20y=20el=20recurso=20PetsResource?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Se incluyen los test para comprobar la entidad Pet y el recurso PetsResource. Se incluyen todos los ficheros necesarios para la ejecución de dichos test. Además se corrigen algunos fallos detectados en PetsResource y en PetsDAO --- .../java/es/uvigo/esei/daa/dao/PetsDAO.java | 103 ++----- .../es/uvigo/esei/daa/rest/PetsResource.java | 23 +- src/main/webapp/js/dao/pets.js | 6 - .../esei/daa/DAAExampleTestApplication.java | 3 +- .../uvigo/esei/daa/dataset/PetsDataset.java | 84 ++++++ .../uvigo/esei/daa/entities/PetUnitTest.java | 2 +- .../daa/filters/AuthorizationFilterPets.java | 128 ++++++++ .../uvigo/esei/daa/matchers/IsEqualToPet.java | 57 ++++ .../esei/daa/rest/PeopleResourceTest.java | 3 +- .../uvigo/esei/daa/rest/PetsResourceTest.java | 278 ++++++++++++++++++ .../esei/daa/suites/IntegrationTestSuite.java | 4 +- src/test/resources/datasets/dataset-add.xml | 6 + .../resources/datasets/dataset-addPet.xml | 25 ++ .../resources/datasets/dataset-delete.xml | 8 +- .../resources/datasets/dataset-deletePet.xml | 23 ++ .../resources/datasets/dataset-modify.xml | 8 + .../resources/datasets/dataset-modifyPet.xml | 26 ++ src/test/resources/datasets/dataset.dtd | 9 +- src/test/resources/datasets/dataset.xml | 6 + src/test/resources/db/hsqldb-drop.sql | 1 + src/test/resources/db/hsqldb.sql | 8 + 21 files changed, 696 insertions(+), 115 deletions(-) create mode 100644 src/test/java/es/uvigo/esei/daa/dataset/PetsDataset.java create mode 100644 src/test/java/es/uvigo/esei/daa/filters/AuthorizationFilterPets.java create mode 100644 src/test/java/es/uvigo/esei/daa/matchers/IsEqualToPet.java create mode 100644 src/test/java/es/uvigo/esei/daa/rest/PetsResourceTest.java create mode 100644 src/test/resources/datasets/dataset-addPet.xml create mode 100644 src/test/resources/datasets/dataset-deletePet.xml create mode 100644 src/test/resources/datasets/dataset-modifyPet.xml diff --git a/src/main/java/es/uvigo/esei/daa/dao/PetsDAO.java b/src/main/java/es/uvigo/esei/daa/dao/PetsDAO.java index 2e73805..bf1d4d8 100644 --- a/src/main/java/es/uvigo/esei/daa/dao/PetsDAO.java +++ b/src/main/java/es/uvigo/esei/daa/dao/PetsDAO.java @@ -13,47 +13,9 @@ import java.util.logging.Logger; import es.uvigo.esei.daa.entities.Pet; public class PetsDAO extends DAO{ - private final static Logger LOG = Logger.getLogger(PeopleDAO.class.getName()); - - /** - * Returns a pet stored persisted in the system. - * - * @param id_owner identifier of the owner's animal. - * @param id_pet identifier of the id animal. - * @return a pet with the provided identifier. - * @throws DAOException if an error happens while retrieving the pet. - * @throws IllegalArgumentException if the provided id does not corresponds - * with any persisted pet. - */ - public Pet get(int id) - throws DAOException, IllegalArgumentException { - try (final Connection conn = this.getConnection()) { - final String query = "SELECT * FROM pets pt, people po WHERE pt.owner = po.id and pt.id=?"; - - try (final PreparedStatement statement = conn.prepareStatement(query)) { - statement.setInt(1, id); - - try (final ResultSet result = statement.executeQuery()) { - if (result.next()) { - return rowToEntity(result); - } else { - throw new IllegalArgumentException("Invalid id"); - } - } - } - } catch (SQLException e) { - LOG.log(Level.SEVERE, "Error getting a person", e); - throw new DAOException(e); - } - } - - - - + private final static Logger LOG = Logger.getLogger(PeopleDAO.class.getName()); - - - /** + /** * Returns a list with all the people persisted in the system. * * @return a list with all the people persisted in the system. @@ -64,7 +26,7 @@ public class PetsDAO extends DAO{ final String query = "SELECT * FROM pets pt, people po WHERE pt.owner = po.id and po.id=?"; try (final PreparedStatement statement = conn.prepareStatement(query)) { - statement.setInt(1, id); + statement.setInt(1, id); try (final ResultSet result = statement.executeQuery()) { final List pets = new LinkedList<>(); @@ -83,38 +45,6 @@ public class PetsDAO extends DAO{ } - - - - /** - * Returns a list with all the people persisted in the system. - * - * @return a list with all the people persisted in the system. - * @throws DAOException if an error happens while retrieving the people. - */ - public List list() throws DAOException { - try (final Connection conn = this.getConnection()) { - final String query = "SELECT * FROM pets"; - - try (final PreparedStatement statement = conn.prepareStatement(query)) { - try (final ResultSet result = statement.executeQuery()) { - final List pets = new LinkedList<>(); - - while (result.next()) { - pets.add(rowToEntity(result)); - } - - return pets; - } - } - } catch (SQLException e) { - LOG.log(Level.SEVERE, "Error listing pets", e); - throw new DAOException(e); - } - } - - - /** * Persists a new person in the system. An identifier will be assigned * automatically to the new person. @@ -125,24 +55,32 @@ public class PetsDAO extends DAO{ * @throws DAOException if an error happens while persisting the new person. * @throws IllegalArgumentException if the name or surname are {@code null}. */ - public Pet add(int owner, String name, float weight) + public Pet add(int owner, String name, String weight) throws DAOException, IllegalArgumentException { + if (name == null) { throw new IllegalArgumentException("name can't be null"); } - + if (owner == 0) { + throw new IllegalArgumentException("owner can't be null"); + } + if (weight == null) { + throw new IllegalArgumentException("weight can't be null"); + } try (Connection conn = this.getConnection()) { + final String query = "INSERT INTO pets VALUES(null, ?, ?, ?)"; try (PreparedStatement statement = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) { + statement.setInt(1, owner); statement.setString(2, name); - statement.setFloat(3, weight); + statement.setFloat(3, Float.parseFloat(weight)); if (statement.executeUpdate() == 1) { try (ResultSet resultKeys = statement.getGeneratedKeys()) { if (resultKeys.next()) { - return new Pet(resultKeys.getInt(1), owner, name, weight); + return new Pet(resultKeys.getInt(1), owner, name, Float.parseFloat(weight)); } else { LOG.log(Level.SEVERE, "Error retrieving inserted id"); throw new SQLException("Error retrieving inserted id"); @@ -175,13 +113,12 @@ public class PetsDAO extends DAO{ } try (Connection conn = this.getConnection()) { - final String query = "UPDATE pets SET owner=?, name=?, weight=? WHERE id=?"; + final String query = "UPDATE pets SET name=?, weight=? WHERE id=?"; try (PreparedStatement statement = conn.prepareStatement(query)) { - statement.setInt(1, pet.getOwner()); - statement.setString(2, pet.getName()); - statement.setFloat(3, pet.getWeight()); - statement.setInt(4, pet.getId()); + statement.setString(1, pet.getName()); + statement.setFloat(2, pet.getWeight()); + statement.setInt(3, pet.getId()); if (statement.executeUpdate() != 1) { throw new IllegalArgumentException("owner, name and weight can't be null"); @@ -225,7 +162,7 @@ public class PetsDAO extends DAO{ row.getInt("id"), row.getInt("owner"), row.getString("name"), - row.getFloat("weight") + (row.getFloat("weight") * 100)/100 ); } diff --git a/src/main/java/es/uvigo/esei/daa/rest/PetsResource.java b/src/main/java/es/uvigo/esei/daa/rest/PetsResource.java index a9d948c..1f04765 100644 --- a/src/main/java/es/uvigo/esei/daa/rest/PetsResource.java +++ b/src/main/java/es/uvigo/esei/daa/rest/PetsResource.java @@ -70,22 +70,6 @@ public class PetsResource { } } - /** - * Returns the complete list of pets stored in the system. - * - * @return a 200 OK response with the complete list of pets stored in the - * system. If an error happens while retrieving the list, a 500 Internal - * Server Error response with an error message will be returned. - */ - @GET - public Response list() { - try { - return Response.ok(this.dao.list()).build(); - } catch (DAOException e) { - LOG.log(Level.SEVERE, "Error listing pets", e); - return Response.serverError().entity(e.getMessage()).build(); - } - } /** * Creates a new person in the system. @@ -100,17 +84,16 @@ public class PetsResource { */ @POST public Response add( - @FormParam("owner") int owner, + @FormParam("owner") int owner, @FormParam("name") String name, @FormParam("weight") Float weight ) { try { - final Pet newPet = this.dao.add(owner, name, weight); + final Pet newPet = this.dao.add(owner, name, String.valueOf(weight)); return Response.ok(newPet).build(); } catch (IllegalArgumentException iae) { LOG.log(Level.FINE, "Invalid pet id in add method", iae); - return Response.status(Response.Status.BAD_REQUEST) .entity(iae.getMessage()) .build(); @@ -149,7 +132,7 @@ public class PetsResource { return Response.ok(modifiedPet).build(); } catch (NullPointerException npe) { - final String message = String.format("Invalid data for pet (owner: %s, name: %s, weight: %s)", owner, name, weight); + final String message = String.format("Invalid data for pet (name: %s, weight: %s)", name, weight); LOG.log(Level.FINE, message); diff --git a/src/main/webapp/js/dao/pets.js b/src/main/webapp/js/dao/pets.js index a1ef9c4..6a7498a 100644 --- a/src/main/webapp/js/dao/pets.js +++ b/src/main/webapp/js/dao/pets.js @@ -16,12 +16,6 @@ var PetsDAO = (function() { }; function PetsDAO() { - this.listPets = function(done, fail, always) { - requestByAjax({ - url : resourcePath, - type : 'GET' - }, done, fail, always); - }; this.addPet = function(pet, done, fail, always) { requestByAjax({ diff --git a/src/test/java/es/uvigo/esei/daa/DAAExampleTestApplication.java b/src/test/java/es/uvigo/esei/daa/DAAExampleTestApplication.java index 43b5809..2896c04 100644 --- a/src/test/java/es/uvigo/esei/daa/DAAExampleTestApplication.java +++ b/src/test/java/es/uvigo/esei/daa/DAAExampleTestApplication.java @@ -8,6 +8,7 @@ import java.util.Set; import javax.ws.rs.ApplicationPath; import es.uvigo.esei.daa.filters.AuthorizationFilter; +import es.uvigo.esei.daa.filters.AuthorizationFilterPets; @ApplicationPath("/rest/*") public class DAAExampleTestApplication extends DAAExampleApplication { @@ -16,7 +17,7 @@ public class DAAExampleTestApplication extends DAAExampleApplication { final Set> classes = new HashSet<>(super.getClasses()); classes.add(AuthorizationFilter.class); - + classes.add(AuthorizationFilterPets.class); return unmodifiableSet(classes); } } diff --git a/src/test/java/es/uvigo/esei/daa/dataset/PetsDataset.java b/src/test/java/es/uvigo/esei/daa/dataset/PetsDataset.java new file mode 100644 index 0000000..b6ffbdb --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/dataset/PetsDataset.java @@ -0,0 +1,84 @@ +package es.uvigo.esei.daa.dataset; + +import static java.util.Arrays.binarySearch; +import static java.util.Arrays.stream; + +import java.util.Arrays; +import java.util.function.Predicate; + +import es.uvigo.esei.daa.entities.Pet; + +public final class PetsDataset { + private PetsDataset() {} + + public static Pet[] pets() { + return new Pet[] { + new Pet(1, 4, "Pintitas", 5.15f), + new Pet(2, 1, "Yami", 3.15f), + new Pet(3, 2, "Kirara", 4.45f), + new Pet(4, 2, "Pelusa", 6.7f), + new Pet(5, 1, "Cotufo", 3.2f) + }; + } + + public static Pet[] petsToListWithOwnerIdTest() { + return new Pet[] { + new Pet(2, 1, "Yami", 3.15f), + new Pet(5, 1, "Cotufo", 3.2f) + }; + } + + public static Pet[] petsWithout(int ... ids) { + Arrays.sort(ids); + + final Predicate hasValidId = pet -> + binarySearch(ids, pet.getId()) < 0; + + return stream(pets()) + .filter(hasValidId) + .toArray(Pet[]::new); + } + + public static Pet pet(int id) { + return stream(pets()) + .filter(pet -> pet.getId() == id) + .findAny() + .orElseThrow(IllegalArgumentException::new); + } + + public static int existentId() { + return 5; + } + + public static int existentOwnerId() { + return 1; + } + + public static int nonExistentId() { + return 1234; + } + + public static Pet existentPet() { + return pet(existentId()); + } + + public static Pet nonExistentPet() { + return new Pet(nonExistentId(), 2, "Luna", 3.57f); + } + + public static int newOwner() { + return 1; + } + + public static String newName() { + return "Sol"; + } + + public static Float newWeight() { + return 6f; + } + + public static Pet newPet() { + return new Pet(pets().length + 1, newOwner(), newName(), newWeight()); + } +} diff --git a/src/test/java/es/uvigo/esei/daa/entities/PetUnitTest.java b/src/test/java/es/uvigo/esei/daa/entities/PetUnitTest.java index 7f12262..4f5615f 100644 --- a/src/test/java/es/uvigo/esei/daa/entities/PetUnitTest.java +++ b/src/test/java/es/uvigo/esei/daa/entities/PetUnitTest.java @@ -97,7 +97,7 @@ public class PetUnitTest { @Test public void testEqualsHashcode() { EqualsVerifier.forClass(Pet.class) - .withIgnoredFields("name", "surname") + .withIgnoredFields("owner", "name", "weight") .suppress(Warning.STRICT_INHERITANCE) .suppress(Warning.NONFINAL_FIELDS).verify(); } diff --git a/src/test/java/es/uvigo/esei/daa/filters/AuthorizationFilterPets.java b/src/test/java/es/uvigo/esei/daa/filters/AuthorizationFilterPets.java new file mode 100644 index 0000000..e3edb9f --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/filters/AuthorizationFilterPets.java @@ -0,0 +1,128 @@ +package es.uvigo.esei.daa.filters; + +import java.io.IOException; +import java.security.Principal; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.PathSegment; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.SecurityContext; +import javax.ws.rs.ext.Provider; + +import es.uvigo.esei.daa.dao.DAOException; +import es.uvigo.esei.daa.dao.UsersDAO; +import es.uvigo.esei.daa.entities.User; + +/** + * This performs the Basic HTTP authentication following (almost) the same + * rules as the defined in the web.xml file. + * + * @author Miguel Reboiro Jato + */ +@Provider +@Priority(Priorities.AUTHENTICATION) +public class AuthorizationFilterPets implements ContainerRequestFilter { + // Add here the list of REST paths that an administrator can access. + private final static List ADMIN_PATHS = Arrays.asList("pets"); + + private final UsersDAO dao; + + public AuthorizationFilterPets() { + this.dao = new UsersDAO(); + } + + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + // Get the authentication passed in HTTP headers parameters + final String auth = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION); + + if (auth == null) { + requestContext.abortWith(createResponse()); + } else { + final byte[] decodedToken = Base64.getDecoder() + .decode(auth.substring(6)); + + final String userColonPass = new String(decodedToken); + final String[] userPass = userColonPass.split(":", 2); + + if (userPass.length == 2) { + try { + if (this.dao.checkLogin(userPass[0], userPass[1])) { + final User user = this.dao.get(userPass[0]); + + if (isAdminPath(requestContext) && !user.getRole().equals("ADMIN")) { + requestContext.abortWith(createResponse()); + } else { + requestContext.setSecurityContext(new UserSecurityContext(user)); + } + } else { + requestContext.abortWith(createResponse()); + } + } catch (DAOException e) { + requestContext.abortWith(createResponse()); + } + } else { + requestContext.abortWith(createResponse()); + } + } + } + + private static boolean isAdminPath(ContainerRequestContext context) { + final List pathSegments = context.getUriInfo().getPathSegments(); + + if (pathSegments.isEmpty()) { + return false; + } else { + final String path = pathSegments.get(0).getPath(); + return ADMIN_PATHS.contains(path); + } + } + + private static Response createResponse() { + return Response.status(Status.UNAUTHORIZED) + .header(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"DAAExample\"") + .entity("Page requires login.") + .build(); + } + + private static final class UserSecurityContext implements SecurityContext { + private final User user; + + private UserSecurityContext(User user) { + this.user = user; + } + + @Override + public boolean isUserInRole(String role) { + return user.getRole().equals(role); + } + + @Override + public boolean isSecure() { + return false; + } + + @Override + public Principal getUserPrincipal() { + return new Principal() { + @Override + public String getName() { + return user.getLogin(); + } + }; + } + + @Override + public String getAuthenticationScheme() { + return SecurityContext.BASIC_AUTH; + } + } +} diff --git a/src/test/java/es/uvigo/esei/daa/matchers/IsEqualToPet.java b/src/test/java/es/uvigo/esei/daa/matchers/IsEqualToPet.java new file mode 100644 index 0000000..860c5e3 --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/matchers/IsEqualToPet.java @@ -0,0 +1,57 @@ +package es.uvigo.esei.daa.matchers; + +import org.hamcrest.Factory; +import org.hamcrest.Matcher; + +import es.uvigo.esei.daa.entities.Pet; + +public class IsEqualToPet extends IsEqualToEntity { + public IsEqualToPet(Pet entity) { + super(entity); + } + + @Override + protected boolean matchesSafely(Pet actual) { + this.clearDescribeTo(); + + if (actual == null) { + this.addTemplatedDescription("actual", expected.toString()); + return false; + } else { + return checkAttribute("id", Pet::getId, actual) + && checkAttribute("owner", Pet::getOwner, actual) + && checkAttribute("name", Pet::getName, actual) + && checkAttribute("weight", Pet::getWeight, actual); + } + } + + /** + * Factory method that creates a new {@link IsEqualToEntity} matcher with + * the provided {@link Person} as the expected value. + * + * @param person the expected person. + * @return a new {@link IsEqualToEntity} matcher with the provided + * {@link Person} as the expected value. + */ + @Factory + public static IsEqualToPet equalsToPet(Pet pet) { + return new IsEqualToPet(pet); + } + + /** + * Factory method that returns a new {@link Matcher} that includes several + * {@link IsEqualToPerson} matchers, each one using an {@link Person} of the + * provided ones as the expected value. + * + * @param persons the persons to be used as the expected values. + * @return a new {@link Matcher} that includes several + * {@link IsEqualToPerson} matchers, each one using an {@link Person} of the + * provided ones as the expected value. + * @see IsEqualToEntity#containsEntityInAnyOrder(java.util.function.Function, Object...) + */ + @Factory + public static Matcher> containsPetsInAnyOrder(Pet ... peets) { + return containsEntityInAnyOrder(IsEqualToPet::equalsToPet, peets); + } + +} diff --git a/src/test/java/es/uvigo/esei/daa/rest/PeopleResourceTest.java b/src/test/java/es/uvigo/esei/daa/rest/PeopleResourceTest.java index 1e02638..975154c 100644 --- a/src/test/java/es/uvigo/esei/daa/rest/PeopleResourceTest.java +++ b/src/test/java/es/uvigo/esei/daa/rest/PeopleResourceTest.java @@ -91,7 +91,7 @@ public class PeopleResourceTest extends JerseyTest { assertThat(response, hasOkStatus()); final List people = response.readEntity(new GenericType>(){}); - + System.out.println(people.toString()); assertThat(people, containsPeopleInAnyOrder(people())); } @@ -100,6 +100,7 @@ public class PeopleResourceTest extends JerseyTest { final Response response = target("people").request() .header("Authorization", "Basic " + userToken(normalLogin())) .get(); + assertThat(response, hasUnauthorized()); } diff --git a/src/test/java/es/uvigo/esei/daa/rest/PetsResourceTest.java b/src/test/java/es/uvigo/esei/daa/rest/PetsResourceTest.java new file mode 100644 index 0000000..b32ddaf --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/rest/PetsResourceTest.java @@ -0,0 +1,278 @@ +package es.uvigo.esei.daa.rest; + + +import static es.uvigo.esei.daa.dataset.PeopleDataset.existentPerson; +import static es.uvigo.esei.daa.dataset.PetsDataset.existentId; +import static es.uvigo.esei.daa.dataset.PetsDataset.existentOwnerId; +import static es.uvigo.esei.daa.dataset.PetsDataset.petsToListWithOwnerIdTest; +import static es.uvigo.esei.daa.dataset.PetsDataset.existentPet; +import static es.uvigo.esei.daa.dataset.PetsDataset.newName; +import static es.uvigo.esei.daa.dataset.PetsDataset.newPet; +import static es.uvigo.esei.daa.dataset.PetsDataset.newOwner; +import static es.uvigo.esei.daa.dataset.PetsDataset.newWeight; +import static es.uvigo.esei.daa.dataset.PetsDataset.nonExistentId; +import static es.uvigo.esei.daa.dataset.PetsDataset.pets; +import static es.uvigo.esei.daa.dataset.UsersDataset.adminLogin; +import static es.uvigo.esei.daa.dataset.UsersDataset.normalLogin; +import static es.uvigo.esei.daa.dataset.UsersDataset.userToken; +import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasBadRequestStatus; +import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasOkStatus; +import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasUnauthorized; +import static es.uvigo.esei.daa.matchers.IsEqualToPerson.equalsToPerson; +import static es.uvigo.esei.daa.matchers.IsEqualToPet.containsPetsInAnyOrder; +import static es.uvigo.esei.daa.matchers.IsEqualToPet.equalsToPet; +import static javax.ws.rs.client.Entity.entity; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + + +import java.io.IOException; +import java.util.List; + +import javax.sql.DataSource; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; +import com.github.springtestdbunit.DbUnitTestExecutionListener; +import com.github.springtestdbunit.annotation.DatabaseSetup; +import com.github.springtestdbunit.annotation.ExpectedDatabase; + +import es.uvigo.esei.daa.DAAExampleTestApplication; +import es.uvigo.esei.daa.entities.Person; +import es.uvigo.esei.daa.entities.Pet; +import es.uvigo.esei.daa.listeners.ApplicationContextBinding; +import es.uvigo.esei.daa.listeners.ApplicationContextJndiBindingTestExecutionListener; +import es.uvigo.esei.daa.listeners.DbManagement; +import es.uvigo.esei.daa.listeners.DbManagementTestExecutionListener; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:contexts/mem-context.xml") +@TestExecutionListeners({ + DbUnitTestExecutionListener.class, + DbManagementTestExecutionListener.class, + ApplicationContextJndiBindingTestExecutionListener.class +}) +@ApplicationContextBinding( + jndiUrl = "java:/comp/env/jdbc/daaexample", + type = DataSource.class +) +@DbManagement( + create = "classpath:db/hsqldb.sql", + drop = "classpath:db/hsqldb-drop.sql" +) +@DatabaseSetup("/datasets/dataset.xml") +@ExpectedDatabase("/datasets/dataset.xml") +public class PetsResourceTest extends JerseyTest { + @Override + protected Application configure() { + return new DAAExampleTestApplication(); + } + + @Override + protected void configureClient(ClientConfig config) { + super.configureClient(config); + + // Enables JSON transformation in client + config.register(JacksonJsonProvider.class); + config.property("com.sun.jersey.api.json.POJOMappingFeature", Boolean.TRUE); + } + + @Test + public void testListWithOwnerId() throws IOException { + final Response response = target("pets/" + existentOwnerId()).request() + .header("Authorization", "Basic " + userToken(adminLogin())) + .get(); + assertThat(response, hasOkStatus()); + + final List pets = response.readEntity(new GenericType>(){}); + assertThat(pets, containsPetsInAnyOrder(petsToListWithOwnerIdTest())); + } + + @Test + public void testListUnauthorized() throws IOException { + final Response response = target("pets/" + existentId()).request() + .header("Authorization", "Basic " + userToken(normalLogin())) + .get(); + assertThat(response, hasUnauthorized()); + } + + + @Test + @ExpectedDatabase("/datasets/dataset-addPet.xml") + public void testAdd() throws IOException { + final Form form = new Form(); + form.param("owner", Integer.toString(newOwner())); + form.param("name", newName()); + form.param("weight", Float.toString(newWeight())); + + final Response response = target("pets").request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + assertThat(response, hasOkStatus()); + + final Pet pet = response.readEntity(Pet.class); + + assertThat(pet, is(equalsToPet(newPet()))); + } + + @Test + public void testAddMissingName() throws IOException { + final Form form = new Form(); + form.param("owner", Integer.toString(newOwner())); + form.param("weight", Float.toString(newWeight())); + + final Response response = target("pets").request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + public void testAddMissingOwner() throws IOException { + final Form form = new Form(); + form.param("name", newName()); + form.param("weight", Float.toString(newWeight())); + + final Response response = target("pets").request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + public void testAddMissingWeight() throws IOException { + final Form form = new Form(); + form.param("owner", Integer.toString(newOwner())); + form.param("name", newName()); + + + final Response response = target("pets").request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + @ExpectedDatabase("/datasets/dataset-modifyPet.xml") + public void testModify() throws IOException { + final Form form = new Form(); + form.param("owner", Integer.toString(newOwner())); + form.param("name", newName()); + form.param("weight", Float.toString(newWeight())); + + final Response response = target("pets/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + assertThat(response, hasOkStatus()); + + final Pet modifiedPet = response.readEntity(Pet.class); + + final Pet pet = existentPet(); + pet.setName(newName()); + pet.setWeight(newWeight()); + + assertThat(modifiedPet, is(equalsToPet(pet))); + } + + @Test + public void testModifyUnauthorized() throws IOException { + final Form form = new Form(); + form.param("owner", Integer.toString(newOwner())); + form.param("name", newName()); + form.param("weight", Float.toString(newWeight())); + + final Response response = target("pets/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(normalLogin())) + .put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasUnauthorized()); + } + + @Test + public void testModifyName() throws IOException { + final Form form = new Form(); + form.param("name", newName()); + + final Response response = target("pets/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + public void testModifyWeight() throws IOException { + final Form form = new Form(); + form.param("weight", Float.toString(newWeight())); + + final Response response = target("pets/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + public void testModifyInvalidId() throws IOException { + final Form form = new Form(); + form.param("owner", Integer.toString(newOwner())); + form.param("name", newName()); + form.param("weight", Float.toString(newWeight())); + + final Response response = target("pets/" + nonExistentId()).request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .put(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + @ExpectedDatabase("/datasets/dataset-deletePet.xml") + public void testDelete() throws IOException { + final Response response = target("pets/" + existentId()).request() + .header("Authorization", "Basic " + userToken(adminLogin())) + .delete(); + + assertThat(response, hasOkStatus()); + + final Integer deletedId = response.readEntity(Integer.class); + + assertThat(deletedId, is(equalTo(existentId()))); + } + + @Test + public void testDeleteUnauthorized() throws IOException { + final Response response = target("pets/" + existentId()).request() + .header("Authorization", "Basic " + userToken(normalLogin())) + .delete(); + + assertThat(response, hasUnauthorized()); + } + + @Test + public void testDeleteInvalidId() throws IOException { + final Response response = target("pets/" + nonExistentId()).request() + .header("Authorization", "Basic " + userToken(adminLogin())) + .delete(); + + assertThat(response, hasBadRequestStatus()); + } + +} diff --git a/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java b/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java index 3f0c667..10f13b2 100644 --- a/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java +++ b/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java @@ -5,11 +5,13 @@ import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; import es.uvigo.esei.daa.rest.PeopleResourceTest; +import es.uvigo.esei.daa.rest.PetsResourceTest; import es.uvigo.esei.daa.rest.UsersResourceTest; @SuiteClasses({ PeopleResourceTest.class, - UsersResourceTest.class + UsersResourceTest.class, + PetsResourceTest.class }) @RunWith(Suite.class) public class IntegrationTestSuite { diff --git a/src/test/resources/datasets/dataset-add.xml b/src/test/resources/datasets/dataset-add.xml index 9a75a99..197fa9f 100644 --- a/src/test/resources/datasets/dataset-add.xml +++ b/src/test/resources/datasets/dataset-add.xml @@ -16,4 +16,10 @@ + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-addPet.xml b/src/test/resources/datasets/dataset-addPet.xml new file mode 100644 index 0000000..9be5b8d --- /dev/null +++ b/src/test/resources/datasets/dataset-addPet.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-delete.xml b/src/test/resources/datasets/dataset-delete.xml index e49223d..5e9e817 100644 --- a/src/test/resources/datasets/dataset-delete.xml +++ b/src/test/resources/datasets/dataset-delete.xml @@ -11,7 +11,13 @@ - + + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-deletePet.xml b/src/test/resources/datasets/dataset-deletePet.xml new file mode 100644 index 0000000..0a17892 --- /dev/null +++ b/src/test/resources/datasets/dataset-deletePet.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-modify.xml b/src/test/resources/datasets/dataset-modify.xml index 6e2dfc9..01e651c 100644 --- a/src/test/resources/datasets/dataset-modify.xml +++ b/src/test/resources/datasets/dataset-modify.xml @@ -12,7 +12,15 @@ + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-modifyPet.xml b/src/test/resources/datasets/dataset-modifyPet.xml new file mode 100644 index 0000000..7e3ad3d --- /dev/null +++ b/src/test/resources/datasets/dataset-modifyPet.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset.dtd b/src/test/resources/datasets/dataset.dtd index e64500f..484c6ae 100644 --- a/src/test/resources/datasets/dataset.dtd +++ b/src/test/resources/datasets/dataset.dtd @@ -1,6 +1,7 @@ - + + + diff --git a/src/test/resources/datasets/dataset.xml b/src/test/resources/datasets/dataset.xml index 3f48cc9..2c093f9 100644 --- a/src/test/resources/datasets/dataset.xml +++ b/src/test/resources/datasets/dataset.xml @@ -15,4 +15,10 @@ + + + + + + \ No newline at end of file diff --git a/src/test/resources/db/hsqldb-drop.sql b/src/test/resources/db/hsqldb-drop.sql index 31f8643..3ad2bc1 100644 --- a/src/test/resources/db/hsqldb-drop.sql +++ b/src/test/resources/db/hsqldb-drop.sql @@ -1,2 +1,3 @@ DROP TABLE People IF EXISTS; DROP TABLE Users IF EXISTS; +DROP TABLE Pets IF EXISTS; \ No newline at end of file diff --git a/src/test/resources/db/hsqldb.sql b/src/test/resources/db/hsqldb.sql index a629441..28b7457 100644 --- a/src/test/resources/db/hsqldb.sql +++ b/src/test/resources/db/hsqldb.sql @@ -10,4 +10,12 @@ CREATE TABLE users ( password VARCHAR(64) NOT NULL, role VARCHAR(5) NOT NULL, PRIMARY KEY (login) +); + +CREATE TABLE pets ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) NOT NULL, + owner INTEGER NOT NULL, + name VARCHAR(50) NOT NULL, + weight FLOAT NOT NULL, + PRIMARY KEY (id) ); \ No newline at end of file -- 2.18.1