From efd736a58648d1481b81c3cdbb36b6af5bc25a04 Mon Sep 17 00:00:00 2001 From: miferreiro Date: Thu, 21 Feb 2019 18:06:48 +0100 Subject: [PATCH] Created the unit tests for the pet DAO For this, the PetsDataset class has been created in order to have test data and verify the correct functioning of the DAO. In addition, a matcher has been added to compare pets. --- .../uvigo/esei/daa/dao/PetsDAOUnitTest.java | 291 ++++++++++++++++++ .../uvigo/esei/daa/dataset/PetsDataset.java | 98 ++++++ .../uvigo/esei/daa/matchers/IsEqualToPet.java | 59 ++++ .../uvigo/esei/daa/suites/UnitTestSuite.java | 11 + 4 files changed, 459 insertions(+) create mode 100644 src/test/java/es/uvigo/esei/daa/dao/PetsDAOUnitTest.java create mode 100644 src/test/java/es/uvigo/esei/daa/dataset/PetsDataset.java create mode 100644 src/test/java/es/uvigo/esei/daa/matchers/IsEqualToPet.java 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 0000000..542f2f7 --- /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 0000000..b3d20f3 --- /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 0000000..f0a09db --- /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 a21ca36..2afa7fa 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) -- 2.18.1