diff --git a/src/test/java/es/uvigo/esei/daa/dao/PetsDAOUnitTest.java b/src/test/java/es/uvigo/esei/daa/dao/PetsDAOUnitTest.java new file mode 100644 index 0000000000000000000000000000000000000000..542f2f794201ba2f5960d6baf07d0d655aa57d6d --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/dao/PetsDAOUnitTest.java @@ -0,0 +1,291 @@ +package es.uvigo.esei.daa.dao; + +import static es.uvigo.esei.daa.dataset.PetsDataset.existentId; +import static es.uvigo.esei.daa.dataset.PetsDataset.existentIdOwner; +import static es.uvigo.esei.daa.dataset.PetsDataset.existentPet; +import static es.uvigo.esei.daa.dataset.PetsDataset.newPet; +import static es.uvigo.esei.daa.dataset.PetsDataset.newName; +import static es.uvigo.esei.daa.dataset.PetsDataset.newSpecie; +import static es.uvigo.esei.daa.dataset.PetsDataset.newIdOwner; +import static es.uvigo.esei.daa.dataset.PetsDataset.pets; +import static es.uvigo.esei.daa.dataset.PetsDataset.petsOwner; +import static es.uvigo.esei.daa.matchers.IsEqualToPet.equalsToPet; +import static es.uvigo.esei.daa.matchers.IsEqualToPet.containsPetsInAnyOrder; +import static org.easymock.EasyMock.anyString; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.reset; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.sql.SQLException; + +import org.junit.Test; + +import com.mysql.jdbc.Statement; + +import es.uvigo.esei.daa.entities.Pet; +import es.uvigo.esei.daa.util.DatabaseQueryUnitTest; + +public class PetsDAOUnitTest extends DatabaseQueryUnitTest{ + @Test + public void testList() throws Exception { + final Pet[] pets = pets(); + + for (Pet pet : pets) { + expectPetRow(pet); + } + expect(result.next()).andReturn(false); + result.close(); + + replayAll(); + final PetsDAO petsDAO = new PetsDAO(); + + assertThat(petsDAO.list(), containsPetsInAnyOrder(pets)); + } + + @Test(expected = DAOException.class) + public void testListUnexpectedException() throws Exception { + expect(result.next()).andThrow(new SQLException()); + result.close(); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.list(); + } + + @Test + public void testGetPets() throws Exception { + final Pet[] pets = petsOwner(existentIdOwner()); + + for (Pet pet : pets) { + expectPetRow(pet); + } + expect(result.next()).andReturn(false); + result.close(); + + replayAll(); + final PetsDAO petsDAO = new PetsDAO(); + + assertThat(petsDAO.getPets(existentIdOwner()), containsPetsInAnyOrder(pets)); + } + + @Test(expected = DAOException.class) + public void testGetPetsUnexpectedException() throws Exception { + expect(result.next()).andThrow(new SQLException()); + result.close(); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.getPets(existentIdOwner()); + } + + @Test + public void testGet() throws Exception { + final Pet existentPet = existentPet(); + + expectPetRow(existentPet); + result.close(); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + + assertThat(petsDAO.get(existentId()), is(equalTo(existentPet))); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetMissing() throws Exception { + expect(result.next()).andReturn(false); + result.close(); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.get(existentId()); + } + + @Test(expected = DAOException.class) + public void testGetUnexpectedException() throws Exception { + expect(result.next()).andThrow(new SQLException()); + result.close(); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.get(existentId()); + } + + @Test + public void testAdd() throws Exception { + final Pet pet = newPet(); + reset(connection); + expect(connection.prepareStatement(anyString(), eq(Statement.RETURN_GENERATED_KEYS))) + .andReturn(statement); + expect(statement.executeUpdate()).andReturn(1); + expect(statement.getGeneratedKeys()).andReturn(result); + + // Key retrieval + expect(result.next()).andReturn(true); + expect(result.getInt(1)).andReturn(pet.getId()); + connection.close(); + result.close(); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + final Pet newPet = petsDAO.add(pet.getName(), pet.getSpecie(), pet.getIdOwner()); + + assertThat(newPet, is(equalsToPet(pet))); + } + + @Test(expected = IllegalArgumentException.class) + public void testAddNullName() throws Exception { + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + + resetAll(); // No expectations + + petsDAO.add(null, newSpecie(), newIdOwner()); + } + + @Test(expected = IllegalArgumentException.class) + public void testAddNullSpecie() throws Exception { + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + + resetAll(); // No expectations + + petsDAO.add(newName(), null, newIdOwner()); + } + + @Test(expected = DAOException.class) + public void testAddZeroUpdatedRows() throws Exception { + reset(connection); + expect(connection.prepareStatement(anyString(), eq(1))) + .andReturn(statement); + expect(statement.executeUpdate()).andReturn(0); + connection.close(); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.add(newName(), newSpecie(), newIdOwner()); + } + + @Test(expected = DAOException.class) + public void testAddNoGeneratedKey() throws Exception { + reset(connection); + expect(connection.prepareStatement(anyString(), eq(1))) + .andReturn(statement); + expect(statement.executeUpdate()).andReturn(1); + expect(statement.getGeneratedKeys()).andReturn(result); + expect(result.next()).andReturn(false); + result.close(); + connection.close(); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.add(newName(), newSpecie(), newIdOwner()); + } + + @Test(expected = DAOException.class) + public void testAddUnexpectedException() throws Exception { + reset(connection); + expect(connection.prepareStatement(anyString(), eq(1))) + .andReturn(statement); + expect(statement.executeUpdate()).andThrow(new SQLException()); + connection.close(); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.add(newName(), newSpecie(), newIdOwner()); + } + + @Test + public void testDelete() throws Exception { + expect(statement.executeUpdate()).andReturn(1); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.delete(existentId()); + } + + @Test(expected = IllegalArgumentException.class) + public void testDeleteInvalidId() throws Exception { + expect(statement.executeUpdate()).andReturn(0); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.delete(existentId()); + } + + @Test(expected = DAOException.class) + public void testDeleteUnexpectedException() throws Exception { + expect(statement.executeUpdate()).andThrow(new SQLException()); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.delete(existentId()); + } + + @Test + public void testModify() throws Exception { + expect(statement.executeUpdate()).andReturn(1); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.modify(existentPet()); + } + + @Test(expected = IllegalArgumentException.class) + public void testModifyNullPet() throws Exception { + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + + resetAll(); // No expectations + + petsDAO.modify(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testModifyZeroUpdatedRows() throws Exception { + expect(statement.executeUpdate()).andReturn(0); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.modify(existentPet()); + } + + @Test(expected = DAOException.class) + public void testModifyUnexpectedException() throws Exception { + expect(statement.executeUpdate()).andThrow(new SQLException()); + + replayAll(); + + final PetsDAO petsDAO = new PetsDAO(); + petsDAO.modify(existentPet()); + } + + private void expectPetRow(Pet pet) throws SQLException { + expect(result.next()).andReturn(true); + expect(result.getInt("id")).andReturn(pet.getId()); + expect(result.getString("name")).andReturn(pet.getName()); + expect(result.getString("specie")).andReturn(pet.getSpecie()); + expect(result.getInt("idOwner")).andReturn(pet.getIdOwner()); + } + +} 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 0000000000000000000000000000000000000000..b3d20f36402f8467e9c0497ede9b2c4745dad3a0 --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/dataset/PetsDataset.java @@ -0,0 +1,98 @@ +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 class PetsDataset { + private PetsDataset() {} + + + public static Pet[] pets() { + return new Pet[] { + new Pet(1,"Rex","Perro",1), + new Pet(2,"Snoopy","Perro",1), + new Pet(3,"Asno","Asno",2), + new Pet(4,"Bugs Bunny","Conejo",3), + new Pet(5,"Scooby Doo","Perro",4), + new Pet(6,"Jerry","Ratón",1), + new Pet(7,"Mickey Mouse","Ratón",1), + new Pet(8,"Garfield","Gato",6), + new Pet(9,"Piolín","Canario",6), + new Pet(10,"Nemo","Pez",7) + }; + } + + 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[] petsOwner(int ... ids) { + Arrays.sort(ids); + + final Predicate hasValidId = pet -> + binarySearch(ids, pet.getIdOwner()) >= 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 int existentIdOwner() { + return 1; + } + + public static int nonExistentIdOwner() { + return 1234; + } + + public static Pet existentPet() { + return pet(existentId()); + } + + public static Pet nonExistentPet() { + return new Pet(nonExistentId(), "Rex", "Perro",2); + } + + public static String newName() { + return "Dolly"; + } + + public static String newSpecie() { + return "Oveja"; + } + + public static int newIdOwner() { + return 4; + } + public static Pet newPet() { + return new Pet(pets().length + 1, newName(), newSpecie(), newIdOwner()); + } + +} 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..f0a09db26a81f59a2659007396b596c1057085db --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/matchers/IsEqualToPet.java @@ -0,0 +1,59 @@ +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("name", Pet::getName, actual) + && checkAttribute("specie", Pet::getSpecie, actual) + && checkAttribute("idOwner", Pet::getIdOwner, 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/suites/UnitTestSuite.java b/src/test/java/es/uvigo/esei/daa/suites/UnitTestSuite.java index a21ca3663b624f6cf2ea326a347de55ae8f96ca9..2afa7fa0e884ef49e2804a3bcc608e190f928b57 100644 --- a/src/test/java/es/uvigo/esei/daa/suites/UnitTestSuite.java +++ b/src/test/java/es/uvigo/esei/daa/suites/UnitTestSuite.java @@ -5,12 +5,23 @@ import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; import es.uvigo.esei.daa.dao.PeopleDAOUnitTest; +import es.uvigo.esei.daa.dao.PetsDAOUnitTest; import es.uvigo.esei.daa.entities.PersonUnitTest; +import es.uvigo.esei.daa.entities.PetUnitTest; +import es.uvigo.esei.daa.entities.UserUnitTest; import es.uvigo.esei.daa.rest.PeopleResourceUnitTest; +import es.uvigo.esei.daa.rest.PetsResourceUnitTest; @SuiteClasses({ + PersonUnitTest.class, + PetUnitTest.class, + UserUnitTest.class, + PeopleDAOUnitTest.class, + PetsDAOUnitTest.class, + + PetsResourceUnitTest.class, PeopleResourceUnitTest.class }) @RunWith(Suite.class)