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

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 #

The Query setParameter was my stuck point. Thanks for the explanation and example as I was able to mock out the query and get my test through!

Posted by Richard Hawley on September 25, 2018 at 05:23 PM CEST #

Really nice tricks! Best, Brutus from Zurich http://www.haus-blumen.ch/

Posted by Brutus Lally on November 14, 2018 at 05:16 AM CET #

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