0

I have a Canteen class and a Course class (and a BaseEntity). The Canteen class has a set of courses. A course is unique if the composition of name, dateOfServing and the canteen id is unique. I tried to write a test case which should throw an exception if a non-unique course is added to a canteen. But the test doesn't throw any exception at all. Which leads me to believe that I'm doing me Canteen and Course class wrong. The test in question is addDuplicatedCourseToCanteenTest. Anyone got a clue about what I'm doing wrong?

I'm new to TDD as well so any critique in that area is very welcome as well.

BaseEntity.java

@MappedSuperclass
public class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    long id;

    private Date createdAt;
    private Date updatedAt;

    // TODO: http://stackoverflow.com/a/11174297/672009
    // Using the above we wouldn't have to created a CommentRepository
    // Is that a good idea?

    /**
     * http://www.devsniper.com/base-entity-class-in-jpa/
     */
    /** 
     * Sets createdAt before insert
     */
    @PrePersist
    public void setCreationDate() {
        this.setCreatedAt(new Date());
    }

    /** 
     * Sets updatedAt before update 
     */
    @PreUpdate
    public void setChangeDate() {
        this.setUpdatedAt(new Date());
    }

    public Date getCreatedAt() {
        return createdAt;
    }
    protected void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }

    public Date getUpdatedAt() {
        return updatedAt;
    }
    protected void setUpdatedAt(Date updatedAt) {
        this.updatedAt = updatedAt;
    }


    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }


    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (int) (id ^ (id >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        BaseEntity other = (BaseEntity) obj;
        if (id != other.id)
            return false;
        return true;
    }
}

Canteen.java

@Entity
public class Canteen extends BaseEntity {
    private String name;

    // TODO: https://schuchert.wikispaces.com/JPA+Tutorial+1+-+Embedded+Entity
    // http://docs.oracle.com/javaee/6/api/javax/xml/registry/infomodel/PostalAddress.html
    //private Address address;
    //private PostalAddress postalAddress;
    /**
     * In honor of KISS I simply use a simple string address as a holder for the restaurants address.
     * The idea is that the string will contain an address which will be valid according to google maps.
     * Same goes for openingHours, phoneNumber and homepage... KISS wise.
     */
    private String address;
    private String openingHours;    // A string which will be presented within a pre tag
                                    // Eg. <pre>Mandag - Torsdag 10-22
                                    // Fredag - Lørdag 10-24
                                    // Søndag 11-20</pre>
    private String contact;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<Course> courses = new HashSet<>();


    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }

    public String getOpeningHours() {
        return openingHours;
    }
    public void setOpeningHours(String openingHours) {
        this.openingHours = openingHours;
    }

    public String getContact() {
        return contact;
    }
    public void setContact(String contact) {
        this.contact = contact;
    }

    public Set<Course> getCourses() {
        return courses;
    }
    public void setCourses(Set<Course> courses) {
        this.courses = courses;
    }

    public boolean addCourse(Course course)
    {
        return getCourses().add(course);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((address == null) ? 0 : address.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        if (getClass() != obj.getClass())
            return false;
        Canteen other = (Canteen) obj;
        if (address == null) {
            if (other.address != null)
                return false;
        } else if (!address.equals(other.address))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

Course.java

@Entity
public class Course extends BaseEntity {
    private String name;
    private Date dateOfServing;

    @ManyToOne
    private Canteen canteen;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public Date getDateOfServing() {
        return dateOfServing;
    }
    public void setDateOfServing(Date dateOfServing) {
        this.dateOfServing = dateOfServing;
    }

    public Canteen getCanteen() {
        return canteen;
    }
    public void setCanteen(Canteen canteen) {
        this.canteen = canteen;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((canteen == null) ? 0 : canteen.hashCode());
        result = prime * result
                + ((dateOfServing == null) ? 0 : dateOfServing.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        if (getClass() != obj.getClass())
            return false;
        Course other = (Course) obj;
        if (canteen == null) {
            if (other.canteen != null)
                return false;
        } else if (!canteen.equals(other.canteen))
            return false;
        if (dateOfServing == null) {
            if (other.dateOfServing != null)
                return false;
        } else if (!dateOfServing.equals(other.dateOfServing))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

CanteenHasCoursesTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = PersistenceConfig.class)
public class CanteenHasCoursesTest {

    @Autowired
    private CanteenRepository canteenRepository;
    private String canteenName;
    private String courseName;
    private Canteen canteen;
    private Course course;

    @Before
    public void setUp() {
        // Generate unique random name
        canteenName = UUID.randomUUID().toString();
        // Generate unique random name
        courseName = UUID.randomUUID().toString();

        // Create new canteen
        canteen = new Canteen();
        canteen.setName(canteenName);

        // Create new course
        course = new Course();
        course.setName(courseName);
    }

    @Test
    public void addCourseToCanteenTest() {
        // Add course
        canteen.addCourse(course);

        // Save canteen
        canteenRepository.save(canteen);

        // Find it again
        Canteen c = canteenRepository.findOne(canteen.getId());

        // Confirm attributes are as expected
        assertNotNull(c);

        Set<Course> courses = c.getCourses();
        Iterator<Course> it = courses.iterator();
        assertTrue(it.hasNext());

        Course course = it.next();
        assertEquals(courseName, course.getName());
    }

    // TODO: expect some data violation exception
//  @Test(expected = IndexOutOfBoundsException.class)
    @Test
    public void addDuplicatedCourseToCanteenTest() {
        // Add course
        canteen.addCourse(course);
        // Add it again
        canteen.addCourse(course);
        // Save canteen
        canteenRepository.save(canteen);
    }

    @After
    public void tearDown() {
        canteenRepository = null;
        canteenName = null;
        courseName = null;
        canteen = null;
        course = null;
    }

}
user672009
  • 4,379
  • 8
  • 44
  • 77
  • After canteen.addCourse(course); canteen.addCourse(course) what is the size of the Set courses in canteen? – Alan Hay Oct 17 '14 at 13:57
  • It's 1. And it stays one with the way I go about it now. Hibernate caching? – user672009 Oct 17 '14 at 14:13
  • Of course it is one and it has nothing to do with Hibernate. Add it fifty times and it will still be one: From the Java API, "A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied by its name, this interface models the mathematical set abstraction." – Alan Hay Oct 17 '14 at 14:15
  • Thanks, create an answer and I'll mark it as the solution if you care. – user672009 Oct 17 '14 at 14:28

0 Answers0