From 9a6a27240a3df5abb64c288dd47e09fa41410daf Mon Sep 17 00:00:00 2001 From: Nathan Cannon Date: Wed, 19 Sep 2018 10:13:14 +0100 Subject: [PATCH] Implemented testing on ObservationDao. Added Builder for Observation. --- .../neviyn/Observations/api/AverageStats.java | 11 +- .../neviyn/Observations/core/BaseEntity.java | 3 +- .../neviyn/Observations/core/Observation.java | 8 +- .../Observations/core/ObservationEntry.java | 7 +- .../uk/co/neviyn/Observations/core/Site.java | 6 +- .../uk/co/neviyn/Observations/core/Tutor.java | 4 +- .../Observations/dao/ObservationDao.java | 12 +- .../co/neviyn/Observations/dao/SiteDao.java | 4 + .../resources/ObservationResource.java | 25 ++-- .../Observations/dao/ObservationDaoTest.java | 113 ++++++++++++++++++ 10 files changed, 161 insertions(+), 32 deletions(-) create mode 100644 backend/src/test/java/uk/co/neviyn/Observations/dao/ObservationDaoTest.java diff --git a/backend/src/main/java/uk/co/neviyn/Observations/api/AverageStats.java b/backend/src/main/java/uk/co/neviyn/Observations/api/AverageStats.java index ed993a6..a742645 100644 --- a/backend/src/main/java/uk/co/neviyn/Observations/api/AverageStats.java +++ b/backend/src/main/java/uk/co/neviyn/Observations/api/AverageStats.java @@ -1,15 +1,12 @@ package uk.co.neviyn.Observations.api; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import org.joda.time.LocalDate; +import lombok.*; +import org.joda.time.DateTime; @Data @NoArgsConstructor -@RequiredArgsConstructor +@AllArgsConstructor public class AverageStats { @NonNull @@ -18,5 +15,5 @@ public class AverageStats { @NonNull @JsonProperty - private LocalDate date; + private DateTime date; } diff --git a/backend/src/main/java/uk/co/neviyn/Observations/core/BaseEntity.java b/backend/src/main/java/uk/co/neviyn/Observations/core/BaseEntity.java index 1f34e27..43ed287 100644 --- a/backend/src/main/java/uk/co/neviyn/Observations/core/BaseEntity.java +++ b/backend/src/main/java/uk/co/neviyn/Observations/core/BaseEntity.java @@ -9,12 +9,13 @@ import lombok.NonNull; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.MappedSuperclass; +import java.io.Serializable; @Data @MappedSuperclass @NoArgsConstructor @AllArgsConstructor -class BaseEntity { +class BaseEntity implements Serializable { @NonNull @JsonProperty @Id diff --git a/backend/src/main/java/uk/co/neviyn/Observations/core/Observation.java b/backend/src/main/java/uk/co/neviyn/Observations/core/Observation.java index 6898648..872009c 100644 --- a/backend/src/main/java/uk/co/neviyn/Observations/core/Observation.java +++ b/backend/src/main/java/uk/co/neviyn/Observations/core/Observation.java @@ -2,6 +2,7 @@ package uk.co.neviyn.Observations.core; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; import java.util.List; import java.util.Set; @@ -11,12 +12,14 @@ import org.joda.time.DateTime; import javax.persistence.*; @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) @Entity @Table(name = "OBSERVATION") @Data @NoArgsConstructor -@AllArgsConstructor(access = AccessLevel.PROTECTED) -public class Observation extends BaseEntity{ +@AllArgsConstructor +@Builder +public class Observation extends BaseEntity implements Serializable { @JsonProperty @ManyToOne @@ -41,6 +44,7 @@ public class Observation extends BaseEntity{ @NonNull @JsonProperty + @ElementCollection private List observations; @NonNull diff --git a/backend/src/main/java/uk/co/neviyn/Observations/core/ObservationEntry.java b/backend/src/main/java/uk/co/neviyn/Observations/core/ObservationEntry.java index 7238f15..df81b24 100644 --- a/backend/src/main/java/uk/co/neviyn/Observations/core/ObservationEntry.java +++ b/backend/src/main/java/uk/co/neviyn/Observations/core/ObservationEntry.java @@ -3,11 +3,14 @@ package uk.co.neviyn.Observations.core; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; -@EqualsAndHashCode(callSuper = true) +import javax.persistence.Embeddable; +import java.io.Serializable; + @Data @NoArgsConstructor @AllArgsConstructor -public class ObservationEntry extends BaseEntity{ +@Embeddable +public class ObservationEntry implements Serializable { @NonNull @JsonProperty diff --git a/backend/src/main/java/uk/co/neviyn/Observations/core/Site.java b/backend/src/main/java/uk/co/neviyn/Observations/core/Site.java index 3ea673a..a934f92 100644 --- a/backend/src/main/java/uk/co/neviyn/Observations/core/Site.java +++ b/backend/src/main/java/uk/co/neviyn/Observations/core/Site.java @@ -1,6 +1,8 @@ package uk.co.neviyn.Observations.core; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.io.Serializable; import java.util.Set; import lombok.*; @@ -8,11 +10,13 @@ import lombok.*; import javax.persistence.*; @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) @Entity @Table(name = "SITE") @Data @NoArgsConstructor -public class Site extends BaseEntity { +@RequiredArgsConstructor +public class Site extends BaseEntity implements Serializable { @NonNull @JsonProperty diff --git a/backend/src/main/java/uk/co/neviyn/Observations/core/Tutor.java b/backend/src/main/java/uk/co/neviyn/Observations/core/Tutor.java index 6bf5de8..4f6e396 100644 --- a/backend/src/main/java/uk/co/neviyn/Observations/core/Tutor.java +++ b/backend/src/main/java/uk/co/neviyn/Observations/core/Tutor.java @@ -4,14 +4,16 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; import javax.persistence.*; +import java.io.Serializable; import java.util.Set; @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) @Entity @Table(name = "TUTOR") @Data @NoArgsConstructor -public class Tutor extends BaseEntity { +public class Tutor extends BaseEntity implements Serializable { @NonNull @JsonProperty diff --git a/backend/src/main/java/uk/co/neviyn/Observations/dao/ObservationDao.java b/backend/src/main/java/uk/co/neviyn/Observations/dao/ObservationDao.java index e67ba09..e12ca2c 100644 --- a/backend/src/main/java/uk/co/neviyn/Observations/dao/ObservationDao.java +++ b/backend/src/main/java/uk/co/neviyn/Observations/dao/ObservationDao.java @@ -22,19 +22,19 @@ public class ObservationDao extends AbstractDAO { } public List listAll(){ - return list(criteriaQuery()); + return currentSession().createQuery("from Observation", Observation.class).list(); } public List averageStatsForAll(){ - final String hql = "select avg(observation.monitoring), avg(observation.control), avg(observation.conservatism), " + - "avg(observation.teamwork), avg(observation.knowledge) from observation where group by observation.date"; + final String hql = "select new uk.co.neviyn.Observations.api.AverageStats(avg(obs.monitoring), avg(obs.control), avg(obs.conservatism), " + + "avg(obs.teamwork), avg(obs.knowledge), obs.date) from Observation obs group by obs.date order by obs.date"; return currentSession().createQuery(hql, AverageStats.class).list(); } public List averageStatsForSite(Site site){ - final String hql = "select avg(observation.monitoring), avg(observation.control), avg(observation.conservatism), " + - "avg(observation.teamwork), avg(observation.knowledge) from observation where observation.site = :site " + - "group by observation.date"; + final String hql = "select new uk.co.neviyn.Observations.api.AverageStats(avg(obs.monitoring), avg(obs.control), avg(obs.conservatism)," + + "avg(obs.teamwork), avg(obs.knowledge), obs.date) from Observation obs where obs.site = :site " + + "group by obs.date order by obs.date"; return currentSession().createQuery(hql, AverageStats.class).setParameter("site", site).list(); } } diff --git a/backend/src/main/java/uk/co/neviyn/Observations/dao/SiteDao.java b/backend/src/main/java/uk/co/neviyn/Observations/dao/SiteDao.java index a0329b9..b6675c9 100644 --- a/backend/src/main/java/uk/co/neviyn/Observations/dao/SiteDao.java +++ b/backend/src/main/java/uk/co/neviyn/Observations/dao/SiteDao.java @@ -18,4 +18,8 @@ public class SiteDao extends AbstractDAO { public Site get(long id){ return super.get(id); } + + public Site persist(Site site){ + return super.persist(site); + } } diff --git a/backend/src/main/java/uk/co/neviyn/Observations/resources/ObservationResource.java b/backend/src/main/java/uk/co/neviyn/Observations/resources/ObservationResource.java index d75a959..ae096bf 100644 --- a/backend/src/main/java/uk/co/neviyn/Observations/resources/ObservationResource.java +++ b/backend/src/main/java/uk/co/neviyn/Observations/resources/ObservationResource.java @@ -50,18 +50,19 @@ public class ObservationResource { tutors.add(tutorDao.get(l)); } final Site site = siteDao.get(newObservation.getSiteId()); - Observation observation = new Observation(); - observation.setSite(site); - observation.setTutors(tutors); - observation.setObserved(newObservation.getObserved()); - observation.setType(TrainingType.valueOf(newObservation.getType())); - observation.setMonitoring(newObservation.getMonitoring()); - observation.setControl(newObservation.getControl()); - observation.setConservatism(newObservation.getConservatism()); - observation.setTeamwork(newObservation.getTeamwork()); - observation.setKnowledge(newObservation.getKnowledge()); - observation.setObservations(newObservation.getRawData()); - observation.setDate(submissionDate); + Observation observation = Observation.builder() + .site(site) + .tutors(tutors) + .observed(newObservation.getObserved()) + .type(TrainingType.valueOf(newObservation.getType())) + .monitoring(newObservation.getMonitoring()) + .control(newObservation.getControl()) + .conservatism(newObservation.getConservatism()) + .teamwork(newObservation.getTeamwork()) + .knowledge(newObservation.getKnowledge()) + .observations(newObservation.getRawData()) + .date(submissionDate) + .build(); observation = dao.persist(observation); log.info("Created observation with ID " + observation.getId() + " at " + DateTime.now().toString()); return observation.getId(); diff --git a/backend/src/test/java/uk/co/neviyn/Observations/dao/ObservationDaoTest.java b/backend/src/test/java/uk/co/neviyn/Observations/dao/ObservationDaoTest.java new file mode 100644 index 0000000..cc8e9a4 --- /dev/null +++ b/backend/src/test/java/uk/co/neviyn/Observations/dao/ObservationDaoTest.java @@ -0,0 +1,113 @@ +package uk.co.neviyn.Observations.dao; + +import io.dropwizard.testing.junit.DAOTestRule; +import org.apache.commons.lang3.SerializationUtils; +import org.joda.time.DateTime; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import uk.co.neviyn.Observations.api.AverageStats; +import uk.co.neviyn.Observations.core.*; + +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.*; + +public class ObservationDaoTest { + + @Rule + public DAOTestRule testRule = DAOTestRule.newBuilder().addEntityClass(Observation.class).addEntityClass(Site.class).addEntityClass(Tutor.class).build(); + + private ObservationDao dao; + private SiteDao siteDao; + + private final Site site = new Site("Test site"); + + private final Observation observation = new Observation(site, null, "Just a test observation", TrainingType.INITIAL, 1, 2, 3, + 4, 5, Collections.singletonList(new ObservationEntry("MONITORING", 5, "some", "another sum")), DateTime.parse("2018-09-18T00:00:00.000Z") + ); + + @Before + public void setUp() throws Exception { + dao = new ObservationDao(testRule.getSessionFactory()); + siteDao = new SiteDao(testRule.getSessionFactory()); + testRule.inTransaction(() -> siteDao.persist(site)); + } + + @Test + public void persistAndGet(){ + Observation insert = testRule.inTransaction(() -> dao.persist(observation)); + assertNotNull(insert); + assertTrue(insert.getId() > 0); + } + + @Test + public void listAll() { + int numberOfObservations = 5; + testRule.inTransaction(() -> { + for(int i = 0; i < numberOfObservations; i++){ + // Make actual copies, otherwise they will merely overwrite. + dao.persist(SerializationUtils.clone(observation)); + } + }); + List observations = dao.listAll(); + assertNotNull(observations); + assertEquals(numberOfObservations, observations.size()); + } + + @Test + public void averageStatsForAll() { + Observation otherEntry = SerializationUtils.clone(observation); + otherEntry.setMonitoring(5); + otherEntry.setControl(5); + otherEntry.setConservatism(5); + otherEntry.setTeamwork(5); + Observation differentDay = SerializationUtils.clone(observation); + differentDay.setDate(DateTime.now()); + testRule.inTransaction(() -> { + dao.persist(observation); + dao.persist(otherEntry); + dao.persist(differentDay); + }); + List stats = dao.averageStatsForAll(); + assertNotNull(stats); + assertEquals(2, stats.size()); + final AverageStats statObject = stats.get(0); + assertEquals(3, statObject.getMonitoring(), 0); + assertEquals(3.5, statObject.getControl(), 0); + assertEquals(4, statObject.getConservatism(), 0); + assertEquals(4.5, statObject.getTeamwork(), 0); + assertEquals(5, statObject.getKnowledge(), 0); + } + + @Test + public void averageStatsForSite() { + Observation otherEntry = SerializationUtils.clone(observation); + otherEntry.setMonitoring(5); + otherEntry.setControl(5); + otherEntry.setConservatism(5); + otherEntry.setTeamwork(5); + + + Observation hiddenEntity = SerializationUtils.clone(observation); + Site hiddenSite = new Site("Area 51"); + hiddenEntity.setSite(hiddenSite); + testRule.inTransaction(() -> { + dao.persist(observation); + dao.persist(otherEntry); + siteDao.persist(hiddenSite); + dao.persist(hiddenEntity); + }); + List stats = dao.averageStatsForSite(site); + assertNotNull(stats); + assertEquals(1, stats.size()); + final AverageStats statObject = stats.get(0); + assertEquals(3, statObject.getMonitoring(), 0); + assertEquals(3.5, statObject.getControl(), 0); + assertEquals(4, statObject.getConservatism(), 0); + assertEquals(4.5, statObject.getTeamwork(), 0); + assertEquals(5, statObject.getKnowledge(), 0); + } +} \ No newline at end of file