How to test a JPA repository

Here is a typical (Hibernate) JPA repository for saving an entity, a Cookie in this case:

@Entity
@Table(name = "cookie")
public class Cookie {

@Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Integer id;

@Temporal(TemporalType.TIMESTAMP)
 @Column(name = "last_modified")
 private Date lastModified;

}

@Repository
public class CookieRepository {

@PersistenceContext
 EntityManager em;

@Autowired
 TimeService timeService;

@Transactional
 public Cookie createEntity(Cookie cookie) {
 cookie.setLastModified(timeService.getTime().toDate());
 em.persist(cookie);
 return cookie;
 }
}

Writing a unit test for this is not as straightforward as you might think. When a new cookie is created the id is null and only after it gets persisted in the database it gets assigned a value generated by the database.

The EntityManager persist method does not return a value, so how can we mock the entity manager _and_ set the id of the cookie?

Here is the answer:


@RunWith(MockitoJUnitRunner.class)
public class CookieRepositoryTest {

@Mock
 EntityManager em;

@Mock
 TimeService timeService;

@InjectMocks
 CookieRepository underTest = new CookieRepository();

@Test
 public void testCreateEntity() throws Exception {
 Cookie newCookie = new Cookie();

when(timeService.getTime()).thenReturn(new DateTime(DateTimeZone.UTC));

doAnswer(new Answer<Cookie>() {
 @Override
 public Cookie answer(InvocationOnMock invocationOnMock) throws Throwable {
 Object[] args = invocationOnMock.getArguments();
 Cookie cookie = (Cookie) args[0];
 cookie.setId(1);
 return null;
 }

}).when(em).persist(any(Cookie.class));

Cookie persistedCookie = underTest.createEntity(newCookie);
 assertNotNull(persistedCookie.getId());
 }

}

Mockito comes with the doAnswer method, specifically designed for dealing with void methods. With this method you can catch the input of the void method, persist() in this case, manipulate the object which than can be asserted for correctness later in the test.

About these ads

2 thoughts on “How to test a JPA repository

  1. Nice :o)
    For a bit of added awesome there’s the java.lang.Void class… not really what it’s designed for but it gives a nice clear type for the anonymous implementation of Answer:

    List mockList = mock(List.class);
    doAnswer(new Answer() {
    @Override
    public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
    return null;
    }
    }).when(mockList).add(“test”);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s