Search code examples
javaunit-testingjpamockitoentitymanager

How to write unit tests for EntityManager transaction?


I am trying to write a unit test for a existing function that updates a value of a DB field using EntityManager. My unit test should verify that the class updates the value correctly. The current code looks like this:

public class MyClass {
    MyClass(EntityManager em) {
      this.em = em;
    }

    void updateValue() {
      em.getTransaction().begin();
      TypedQuery query = em.createQuery("select a from ...", MyResult.class);
      List<MyResult> results = query.getResultList(); 

      MyResult result = results.get(0);
      result.setInterestingValue(1);
      em.getTransaction().commit();
    }
}

My current approach for the unit testing:

@Mock EntityManager em;
@Mock TypedQuery query;

publid void test() {
   MyClass myClass = new MyClass(em);
   MyResult result = new MyResult();
   ArrayList<MyResult> resultList = new ArrayList<>();
   resultList.add(result);

   when(em.getTransaction()).thenReturn(mock(EntityTransaction.class));
   when(em.createQuery(anyString(), any())).thenReturn(query);
   when(query.getResultList()).thenReturn(resultList);

   myClass.updateValue();

   assertEquals(1, result.getInterestingValue());
}

My unit test above verifies that the MyResult instance is updated. However, it doesn't verify that the value is actually updated through EntityManager. In other words, I'd like to test if EntityManager is correctly used in the existing code. For example, even if I call commit() before setInterestinvValue(1), my test will still pass. Is there a good way to test it?


Solution

  • As commented above, if you use mockito, the solution will be - use inOrder():

    MyResult result = mock(MyResult.class);
    EntityTransaction transaction = mock(EntityTransaction.class)
    
    inOrder.verify(result).setInterestingValue(1);
    inOrder.verify(transaction).commit();