Mocking JPA EntityManager with Query

EntityManager is an interface and can be easily mocked out with https://code.google.com/p/mockito/.

At the same time the EntityManager is also a factory, which creates Query instance, which in turn creates results. Mocking a query involves therefore a three step (=three lines process):


public class RegistrationsTest {

    Registrations cut;

    @Before
    public void init() {
        this.cut = new Registrations();
        this.cut.priceCalculator = mock(VatCalculator.class);

        this.cut.em = mock(EntityManager.class);

		//...
    }

    void mockQuery(String name, List<Registration> results) {

        Query mockedQuery = mock(Query.class);
        when(mockedQuery.getResultList()).thenReturn(results);
        when(this.cut.em.createNamedQuery(name)).thenReturn(mockedQuery);

    }

After this step you can easily return whatever results you like:


    @Test
    public void convertEmptyListToJson() {

        mockQuery(Registration.findAll, Collections.EMPTY_LIST);

        final JsonArray result = this.cut.allAsJson();
        assertNotNull(result);
        assertTrue(result.isEmpty());
    }

If you would like to ignore the parameters, or react to specific query parameters, the method Query::setParameter needs to be mocked as well:


  when(mockedQuery.setParameter(Matchers.anyString(), Matchers.anyObject())).thenReturn(mockedQuery);

See the entire unit test: RegistrationsTest.java. The whole example is available as maven archetype.

Usually complex queries are going to be encapsulated in dedicated controls, so it is easier to mock out the whole control instead.

Interested in Java EE Code Quality and Testing? See you at http://workshops.adam-bien.com/about-testing.htm or regular http://airhacks.com


NEW online workshop: WebStandards Igniter (online)

Airport MUC workshops: Java EE 8, Java 9: Bootstrap, Effective, Architectures, Single Page Apps, Progressive Web Apps, HTML 5, ES 6, CSS 3 and Microservices

Podcast: airhacks.fm and newsletter: airhacks.news

A book about rethinking Java EE Patterns

Comments:

Just a short note: You can use Mockito annotations to reduce some of your setup code, i.e.:

@RunWith(MockitoJUnitRunner.class)
public class RegistrationsTest {

@InjectMocks
Registrations cut;

@Mock
VatCalculator priceCalculator;

@Mock
EntityManager entityManager;

This even allows the Registrations fields priceCalculator and em to be private. I rarely need to verify logs, though, so I'd create them in the cut itself.

Posted by Rüdiger on September 06, 2014 at 09:06 PM CEST #

Nowadays you can create the code needed to mock (or prepare and execute) a @NamedQuery with the anqu method Eclipse plug-in.

It will also be able to cope with the fluent API usage of the Query with all methods such as setFirstResult() or the other versions of setParameter() etc. which are not considered here.

Posted by Mario on March 29, 2016 at 08:15 PM CEST #

Nice

Posted by 12.91.218.206 on June 10, 2016 at 09:19 PM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed
realworldpatterns.com
Online Workshops
...the last 150 posts
...the last 10 comments
License