diff --git a/.idea/dbnavigator.xml b/.idea/dbnavigator.xml
new file mode 100644
index 0000000000000000000000000000000000000000..86603372fcc85d8eaca1dd13543922b652dee74c
--- /dev/null
+++ b/.idea/dbnavigator.xml
@@ -0,0 +1,450 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/es/uvigo/esei/daa/entities/Pet.java b/src/main/java/es/uvigo/esei/daa/entities/Pet.java
index ac9735b5a54a72019fd39a51ef3a94914a86a7a1..20703aaefc51fc6bdf7f01ff8743c5bae9dca57d 100644
--- a/src/main/java/es/uvigo/esei/daa/entities/Pet.java
+++ b/src/main/java/es/uvigo/esei/daa/entities/Pet.java
@@ -74,4 +74,28 @@ public class Pet {
public void setownerID(int ownerID) {
this.ownerID = requireNonNull(ownerID, "ownerID can't be a null reference");
}
+
+ /* NOT UNITESTED
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof Pet))
+ return false;
+ Pet other = (Pet) obj;
+ if (id != other.id)
+ return false;
+ return true;
+ }
+ */
}
diff --git a/src/test/java/es/uvigo/esei/daa/dataset/PetDataset.java b/src/test/java/es/uvigo/esei/daa/dataset/PetDataset.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae2097c778bd9b01a486d8ea528113b7e0947e04
--- /dev/null
+++ b/src/test/java/es/uvigo/esei/daa/dataset/PetDataset.java
@@ -0,0 +1,75 @@
+package es.uvigo.esei.daa.dataset;
+
+import es.uvigo.esei.daa.entities.Pet;
+
+import java.util.Arrays;
+import java.util.function.Predicate;
+
+import static java.util.Arrays.binarySearch;
+import static java.util.Arrays.stream;
+
+public final class PetDataset {
+ private PetDataset() {}
+
+ public static Pet[] pets() {
+ return new Pet[] {
+ new Pet(1, "Pet1", 1),
+ new Pet(2, "Pet2", 1),
+ new Pet(3, "Pet3", 1),
+ new Pet(4, "Pet4", 1),
+ new Pet(5, "Pet5", 1),
+ new Pet(6, "Pet6", 1),
+ new Pet(7, "Pet7", 1),
+ new Pet(8, "Pet8", 1),
+ new Pet(9, "Pet9", 2),
+ new Pet(10, "Pet McPetface", 2)
+ };
+ }
+
+ 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 nonExistentId() {
+ return 1234;
+ }
+
+ public static Pet existentPet() {
+ return Pet(existentId());
+ }
+
+ public static Pet nonExistentPet() {
+ return new Pet(nonExistentId(), "Jane", 1);
+ }
+
+ public static String newName() {
+ return "Pettity Pet";
+ }
+
+ public static String newOwnerID() {
+ return "1";
+ }
+
+ //We add the last pet o the first user, always for testing purposes
+ public static Pet newPet() {
+ return new Pet(pets().length + 1, newName(), 1);
+ }
+}
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 0000000000000000000000000000000000000000..a5d750361d1d15519f1548280b6c482963dd3a21
--- /dev/null
+++ b/src/test/java/es/uvigo/esei/daa/matchers/IsEqualToPet.java
@@ -0,0 +1,55 @@
+package es.uvigo.esei.daa.matchers;
+
+import es.uvigo.esei.daa.entities.Pet;
+import org.hamcrest.Factory;
+import org.hamcrest.Matcher;
+
+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("name", Pet::getName, actual)
+ && checkAttribute("ownerID", Pet::getownerID, actual);
+ }
+ }
+
+ /**
+ * Factory method that creates a new {@link IsEqualToEntity} matcher with
+ * the provided {@link Pet} as the expected value.
+ *
+ * @param pet the expected pet.
+ * @return a new {@link IsEqualToEntity} matcher with the provided
+ * {@link Pet} 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 IsEqualToPet} matchers, each one using an {@link Pet} of the
+ * provided ones as the expected value.
+ *
+ * @param pets the pets to be used as the expected values.
+ * @return a new {@link Matcher} that includes several
+ * {@link IsEqualToPet} matchers, each one using an {@link Pet} of the
+ * provided ones as the expected value.
+ * @see IsEqualToEntity#containsEntityInAnyOrder(java.util.function.Function, Object...)
+ */
+ @Factory
+ public static Matcher> containsPetsInAnyOrder(Pet ... pets) {
+ return containsEntityInAnyOrder(IsEqualToPet::equalsToPet, pets);
+ }
+
+}
diff --git a/src/test/java/es/uvigo/esei/daa/rest/PetResourceTest.java b/src/test/java/es/uvigo/esei/daa/rest/PetResourceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0882ec36ca858a578f5f3ff7d5016578f3ab3be
--- /dev/null
+++ b/src/test/java/es/uvigo/esei/daa/rest/PetResourceTest.java
@@ -0,0 +1,172 @@
+package es.uvigo.esei.daa.rest;
+
+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.DAAExampleApplication;
+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;
+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 javax.sql.DataSource;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.*;
+import java.io.IOException;
+import java.util.List;
+
+import static es.uvigo.esei.daa.dataset.PetDataset.*;
+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.IsEqualToPet.*;
+import static javax.ws.rs.client.Entity.entity;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+@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 PetResourceTest extends JerseyTest {
+ @Override
+ protected Application configure() {
+ return new DAAExampleApplication();
+ }
+
+ @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 testList() throws IOException {
+ final Response response = target("pet/1/").request().get();
+ assertThat(response, hasOkStatus());
+
+ final List pets = response.readEntity(new GenericType>(){});
+ assertThat(pets, containsPetsInAnyOrder(pets()));
+ }
+
+ @Test
+ public void testGet() throws IOException {
+ final Response response = target("pet/1/" + existentId()).request().get();
+ assertThat(response, hasOkStatus());
+
+ final Pet pet = response.readEntity(Pet.class);
+
+ assertThat(pet, is(equalsToPet(existentPet())));
+ }
+
+ @Test
+ public void testGetInvalidId() throws IOException {
+ final Response response = target("pet/1/" + nonExistentId()).request().get();
+
+ assertThat(response, hasBadRequestStatus());
+ }
+
+ @Test
+ @ExpectedDatabase("/datasets/dataset-add.xml")
+ public void testAdd() throws IOException {
+ final Form form = new Form();
+ form.param("name", newName());
+
+ final Response response = target("pet/1")
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .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("ownerID", newOwnerID());
+
+ final Response response = target("pet/1/")
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+
+ assertThat(response, hasBadRequestStatus());
+ }
+
+ @Test
+ @ExpectedDatabase("/datasets/dataset-modify.xml")
+ public void testModify() throws IOException {
+ final Form form = new Form();
+ form.param("name", newName());
+
+ final Response response = target("pet/" + existentId())
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .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());
+
+ assertThat(modifiedPet, is(equalsToPet(pet)));
+ }
+
+ @Test
+ public void testModifyInvalidId() throws IOException {
+ final Form form = new Form();
+ form.param("name", newName());
+ //TODO form.param("surname", newSurname());
+
+ final Response response = target("pet/" + nonExistentId())
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .put(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
+
+ assertThat(response, hasBadRequestStatus());
+ }
+
+ @Test
+ @ExpectedDatabase("/datasets/dataset-delete.xml")
+ public void testDelete() throws IOException {
+ final Response response = target("pet/1/" + existentId()).request().delete();
+
+ assertThat(response, hasOkStatus());
+
+ final Integer deletedId = response.readEntity(Integer.class);
+
+ assertThat(deletedId, is(equalTo(existentId())));
+ }
+
+ @Test
+ public void testDeleteInvalidId() throws IOException {
+ final Response response = target("pet/1/" + nonExistentId()).request().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 822c83f44b63c0c998e6b17c1ab25bddbd750a63..586ee20611a62bec5ace7e7a1909dd4dde2c04d9 100644
--- a/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java
+++ b/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java
@@ -1,5 +1,6 @@
package es.uvigo.esei.daa.suites;
+import es.uvigo.esei.daa.rest.PetResourceTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@@ -11,7 +12,8 @@ import es.uvigo.esei.daa.rest.UsersResourceTest;
@SuiteClasses({
PeopleDAOTest.class,
PeopleResourceTest.class,
- UsersResourceTest.class
+ UsersResourceTest.class,
+ PetResourceTest.class
})
@RunWith(Suite.class)
public class IntegrationTestSuite {
diff --git a/src/test/java/es/uvigo/esei/daa/suites/UnitTestSuite.java b/src/test/java/es/uvigo/esei/daa/suites/UnitTestSuite.java
index a21ca3663b624f6cf2ea326a347de55ae8f96ca9..7e0f157ae249a881212da178d6ccd8bd99fd8ddd 100644
--- a/src/test/java/es/uvigo/esei/daa/suites/UnitTestSuite.java
+++ b/src/test/java/es/uvigo/esei/daa/suites/UnitTestSuite.java
@@ -1,5 +1,6 @@
package es.uvigo.esei.daa.suites;
+import es.uvigo.esei.daa.entities.PetUnitTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@@ -11,7 +12,8 @@ import es.uvigo.esei.daa.rest.PeopleResourceUnitTest;
@SuiteClasses({
PersonUnitTest.class,
PeopleDAOUnitTest.class,
- PeopleResourceUnitTest.class
+ PeopleResourceUnitTest.class,
+ PetUnitTest.class
})
@RunWith(Suite.class)
public class UnitTestSuite {
diff --git a/src/test/resources/datasets/dataset-add.xml b/src/test/resources/datasets/dataset-add.xml
index 832a4a12b2244988bb86eb12ea33aa531677d9da..ab099375afaff6ee87fb552e390f35874d23f6f2 100644
--- a/src/test/resources/datasets/dataset-add.xml
+++ b/src/test/resources/datasets/dataset-add.xml
@@ -16,4 +16,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 7480a415572f1a39d6616d56359f522445b1febd..0de1d8c5ea6a5c8bd690a47e976b8453192e43f6 100644
--- a/src/test/resources/datasets/dataset-delete.xml
+++ b/src/test/resources/datasets/dataset-delete.xml
@@ -14,4 +14,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 f840fb5a8cb65c2ef9fa22d155a1ee4cfcb7433e..0f4233eb94818a51cbd7a0f7fa5cb2798b53e525 100644
--- a/src/test/resources/datasets/dataset-modify.xml
+++ b/src/test/resources/datasets/dataset-modify.xml
@@ -15,4 +15,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/datasets/dataset.dtd b/src/test/resources/datasets/dataset.dtd
index c09a15e688a241515d3452ecec23bbb1d0ee966e..08f9c6472268706c0e8a5b5e879a10b56b046913 100644
--- a/src/test/resources/datasets/dataset.dtd
+++ b/src/test/resources/datasets/dataset.dtd
@@ -1,7 +1,8 @@
-
+
+
+
+
diff --git a/src/test/resources/datasets/dataset.xml b/src/test/resources/datasets/dataset.xml
index 2a7eff17e942477b6dd2bd4a5da60844964f22d7..84e0ef1459b8475a47c1a9ebf322b1184a0e9046 100644
--- a/src/test/resources/datasets/dataset.xml
+++ b/src/test/resources/datasets/dataset.xml
@@ -15,4 +15,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ 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 31f86431b16948308e44087e73b488fc3043628a..448d5036d15aadfdf1bfde602f9c23c1ba2a7602 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 Pet IF EXISTS;
diff --git a/src/test/resources/db/hsqldb.sql b/src/test/resources/db/hsqldb.sql
index 00d02ba483785d9049f6a48f2991a4d7a50fb4be..37ca92b1e4183496b69a39023862a62ae08ca99e 100644
--- a/src/test/resources/db/hsqldb.sql
+++ b/src/test/resources/db/hsqldb.sql
@@ -9,4 +9,11 @@ CREATE TABLE users (
login VARCHAR(100) NOT NULL,
password VARCHAR(64) NOT NULL,
PRIMARY KEY (login)
+);
+
+CREATE TABLE pet (
+ id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) NOT NULL,
+ name VARCHAR(50) NOT NULL,
+ ownerID INTEGER NOT NULL,
+ PRIMARY KEY (id)
);
\ No newline at end of file