Skip to content

Commit fcfdbe7

Browse files
committed
Added tests for service-layer pattern
1 parent 52c483f commit fcfdbe7

File tree

11 files changed

+453
-29
lines changed

11 files changed

+453
-29
lines changed

service-layer/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,10 @@
2222
<artifactId>junit</artifactId>
2323
<scope>test</scope>
2424
</dependency>
25+
<dependency>
26+
<groupId>org.mockito</groupId>
27+
<artifactId>mockito-core</artifactId>
28+
<scope>test</scope>
29+
</dependency>
2530
</dependencies>
2631
</project>

service-layer/src/main/java/com/iluwatar/servicelayer/common/BaseEntity.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,37 @@
1212
*/
1313
@MappedSuperclass
1414
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
15-
public class BaseEntity {
15+
public abstract class BaseEntity {
1616

1717
@Version
1818
private Long version;
19+
20+
/**
21+
* Indicates the unique id of this entity
22+
*
23+
* @return The id of the entity, or 'null' when not persisted
24+
*/
25+
public abstract Long getId();
26+
27+
/**
28+
* Set the id of this entity
29+
*
30+
* @param id The new id
31+
*/
32+
public abstract void setId(Long id);
33+
34+
/**
35+
* Get the name of this entity
36+
*
37+
* @return The name of the entity
38+
*/
39+
public abstract String getName();
40+
41+
/**
42+
* Set the name of this entity
43+
*
44+
* @param name The new name
45+
*/
46+
public abstract void setName(final String name);
47+
1948
}
Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,56 @@
11
package com.iluwatar.servicelayer.hibernate;
22

3-
import org.hibernate.SessionFactory;
4-
import org.hibernate.cfg.Configuration;
5-
63
import com.iluwatar.servicelayer.spell.Spell;
74
import com.iluwatar.servicelayer.spellbook.Spellbook;
85
import com.iluwatar.servicelayer.wizard.Wizard;
96

7+
import org.hibernate.SessionFactory;
8+
import org.hibernate.cfg.Configuration;
9+
1010
/**
11-
*
1211
* Produces the Hibernate {@link SessionFactory}.
13-
*
1412
*/
1513
public class HibernateUtil {
1614

17-
private static final SessionFactory SESSION_FACTORY;
18-
19-
static {
20-
try {
21-
SESSION_FACTORY =
22-
new Configuration().addAnnotatedClass(Wizard.class).addAnnotatedClass(Spellbook.class)
23-
.addAnnotatedClass(Spell.class)
24-
.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
25-
.setProperty("hibernate.connection.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1")
26-
.setProperty("hibernate.current_session_context_class", "thread")
27-
.setProperty("hibernate.show_sql", "true")
28-
.setProperty("hibernate.hbm2ddl.auto", "create-drop").buildSessionFactory();
29-
} catch (Throwable ex) {
30-
System.err.println("Initial SessionFactory creation failed." + ex);
31-
throw new ExceptionInInitializerError(ex);
32-
}
33-
}
15+
/**
16+
* The cached session factory
17+
*/
18+
private static volatile SessionFactory sessionFactory;
3419

3520
private HibernateUtil() {
3621
}
3722

38-
public static SessionFactory getSessionFactory() {
39-
return SESSION_FACTORY;
23+
/**
24+
* Create the current session factory instance, create a new one when there is none yet.
25+
*
26+
* @return The session factory
27+
*/
28+
public static synchronized SessionFactory getSessionFactory() {
29+
if (sessionFactory == null) {
30+
try {
31+
sessionFactory =
32+
new Configuration().addAnnotatedClass(Wizard.class).addAnnotatedClass(Spellbook.class)
33+
.addAnnotatedClass(Spell.class)
34+
.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
35+
.setProperty("hibernate.connection.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1")
36+
.setProperty("hibernate.current_session_context_class", "thread")
37+
.setProperty("hibernate.show_sql", "true")
38+
.setProperty("hibernate.hbm2ddl.auto", "create-drop").buildSessionFactory();
39+
} catch (Throwable ex) {
40+
System.err.println("Initial SessionFactory creation failed." + ex);
41+
throw new ExceptionInInitializerError(ex);
42+
}
43+
}
44+
return sessionFactory;
45+
}
46+
47+
/**
48+
* Drop the current connection, resulting in a create-drop clean database next time. This is
49+
* mainly used for JUnit testing since one test should not influence the other
50+
*/
51+
public static void dropSession() {
52+
getSessionFactory().close();
53+
sessionFactory = null;
4054
}
55+
4156
}

service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package com.iluwatar.servicelayer.spell;
22

3+
import com.iluwatar.servicelayer.common.DaoBaseImpl;
4+
35
import org.hibernate.Criteria;
46
import org.hibernate.Session;
57
import org.hibernate.Transaction;
68
import org.hibernate.criterion.Restrictions;
79

8-
import com.iluwatar.servicelayer.common.DaoBaseImpl;
9-
1010
/**
1111
*
1212
* SpellDao implementation.
@@ -24,7 +24,6 @@ public Spell findByName(String name) {
2424
Criteria criteria = session.createCriteria(persistentClass);
2525
criteria.add(Restrictions.eq("name", name));
2626
result = (Spell) criteria.uniqueResult();
27-
result.getSpellbook().getWizards().size();
2827
tx.commit();
2928
} catch (Exception e) {
3029
if (tx != null) {

service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/Spellbook.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import javax.persistence.CascadeType;
77
import javax.persistence.Column;
88
import javax.persistence.Entity;
9+
import javax.persistence.FetchType;
910
import javax.persistence.GeneratedValue;
1011
import javax.persistence.Id;
1112
import javax.persistence.ManyToMany;
@@ -50,7 +51,7 @@ public void setId(Long id) {
5051

5152
private String name;
5253

53-
@ManyToMany(mappedBy = "spellbooks")
54+
@ManyToMany(mappedBy = "spellbooks", fetch = FetchType.EAGER)
5455
private Set<Wizard> wizards;
5556

5657
@OneToMany(mappedBy = "spellbook", orphanRemoval = true, cascade = CascadeType.ALL)

service-layer/src/test/java/com/iluwatar/servicelayer/app/AppTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.iluwatar.servicelayer.app;
22

3+
import com.iluwatar.servicelayer.hibernate.HibernateUtil;
4+
5+
import org.junit.After;
36
import org.junit.Test;
47

58
/**
@@ -14,4 +17,10 @@ public void test() {
1417
String[] args = {};
1518
App.main(args);
1619
}
20+
21+
@After
22+
public void tearDown() throws Exception {
23+
HibernateUtil.dropSession();
24+
}
25+
1726
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package com.iluwatar.servicelayer.common;
2+
3+
import com.iluwatar.servicelayer.hibernate.HibernateUtil;
4+
5+
import org.junit.After;
6+
import org.junit.Before;
7+
import org.junit.Test;
8+
9+
import java.util.List;
10+
import java.util.concurrent.atomic.AtomicInteger;
11+
import java.util.function.Function;
12+
13+
import static org.junit.Assert.assertEquals;
14+
import static org.junit.Assert.assertNotNull;
15+
import static org.junit.Assert.assertNull;
16+
17+
/**
18+
* Date: 12/28/15 - 10:53 PM
19+
*
20+
* @author Jeroen Meulemeester
21+
*/
22+
public abstract class BaseDaoTest<E extends BaseEntity, D extends DaoBaseImpl<E>> {
23+
24+
/**
25+
* The number of entities stored before each test
26+
*/
27+
private static final int INITIAL_COUNT = 5;
28+
29+
/**
30+
* The unique id generator, shared between all entities
31+
*/
32+
private static final AtomicInteger ID_GENERATOR = new AtomicInteger();
33+
34+
/**
35+
* Factory, used to create new entity instances with the given name
36+
*/
37+
private final Function<String, E> factory;
38+
39+
/**
40+
* The tested data access object
41+
*/
42+
private final D dao;
43+
44+
/**
45+
* Create a new test using the given factory and dao
46+
*
47+
* @param factory The factory, used to create new entity instances with the given name
48+
* @param dao The tested data access object
49+
*/
50+
public BaseDaoTest(final Function<String, E> factory, final D dao) {
51+
this.factory = factory;
52+
this.dao = dao;
53+
}
54+
55+
@Before
56+
public void setUp() throws Exception {
57+
for (int i = 0; i < INITIAL_COUNT; i++) {
58+
final String className = dao.persistentClass.getSimpleName();
59+
final String entityName = String.format("%s%d", className, ID_GENERATOR.incrementAndGet());
60+
this.dao.persist(this.factory.apply(entityName));
61+
}
62+
}
63+
64+
@After
65+
public void tearDown() throws Exception {
66+
HibernateUtil.dropSession();
67+
}
68+
69+
protected final D getDao() {
70+
return this.dao;
71+
}
72+
73+
@Test
74+
public void testFind() throws Exception {
75+
final List<E> all = this.dao.findAll();
76+
for (final E entity : all) {
77+
final E byId = this.dao.find(entity.getId());
78+
assertNotNull(byId);
79+
assertEquals(byId.getId(), byId.getId());
80+
}
81+
}
82+
83+
@Test
84+
public void testDelete() throws Exception {
85+
final List<E> originalEntities = this.dao.findAll();
86+
this.dao.delete(originalEntities.get(1));
87+
this.dao.delete(originalEntities.get(2));
88+
89+
final List<E> entitiesLeft = this.dao.findAll();
90+
assertNotNull(entitiesLeft);
91+
assertEquals(INITIAL_COUNT - 2, entitiesLeft.size());
92+
}
93+
94+
@Test
95+
public void testFindAll() throws Exception {
96+
final List<E> all = this.dao.findAll();
97+
assertNotNull(all);
98+
assertEquals(INITIAL_COUNT, all.size());
99+
}
100+
101+
@Test
102+
public void testSetId() throws Exception {
103+
final E entity = this.factory.apply("name");
104+
assertNull(entity.getId());
105+
106+
final Long expectedId = Long.valueOf(1);
107+
entity.setId(expectedId);
108+
assertEquals(expectedId, entity.getId());
109+
}
110+
111+
@Test
112+
public void testSetName() throws Exception {
113+
final E entity = this.factory.apply("name");
114+
assertEquals("name", entity.getName());
115+
assertEquals("name", entity.toString());
116+
117+
final String expectedName = "new name";
118+
entity.setName(expectedName);
119+
assertEquals(expectedName, entity.getName());
120+
assertEquals(expectedName, entity.toString());
121+
}
122+
123+
}

0 commit comments

Comments
 (0)