Not able to mock persistenceContext in spring boot test

10,041

Solution 1

You can do with with SpringRunner without @DataJpaTest. This worked for me:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {DataRepository.class, EntityManager.class, 
EntityManagerFactory.class})
public class DataRepositoryTest {

    @MockBean
    private EntityManager entityManager;

    @MockBean
    private EntityManagerFactory entityManagerFactory;

    @Autowired
    private DataRepository repository;

    @Before
    public void setup() {
        Mockito.when(entityManagerFactory.createEntityManager()).thenReturn(entityManager);
    }

    @Test
    public void resultTest() {

        Query q = mock(Query.class);
        when(q.setParameter(anyString(), any())).thenReturn(q);
        when(q.getResultList()).thenReturn(createMockReponse());

        when(entityManager.createQuery(anyString())).thenReturn(q);

        Result r = repository.callQuery();


    }

}

Solution 2

I've faced a similar problem and in order to solve it I had to use Springs ReflectionTestUtils in order to inject the mock:

@RunWith(SpringJUnit4ClassRunner.class)
public class RunRepositoryServiceTests {


    private EntityManager entityManagerMock; 


    @Autowired
    private RunRepositoryService runRepositoryService;

    @Before
    public void setUp () {
        entityManagerMock = Mockito.mock(EntityManager.class);
        ReflectionTestUtils.setField(runRepositoryService, "entityManager", entityManagerMock);
    }

    @Test
    public void testFindBySearchCriteria() {

        ....

        when(entityManagerMock.anyMethodToMock(anyObject())).thenReturn(...);

        ....

    }
}

Solution 3

You can use JMockit to easily mock the dependency annotated with @PersistentContext

@RunWith(JMockit.class)
public class RunRepositoryServiceTests {

@Mocked EntityManager entityManager; 

private RunRepositoryService runRepositoryService;

@Before
public void setup(){
    runRepositoryService = new RunRepositoryService();
    Deencapsulation.setField(runRepositoryService, entityManager); //because its a private field
}

@Test
public void testFindBySearchCriteria(@Mocked Query mockQuery) {
    //random fake values for input args
    String searchCriteria = "";
    Integer offset = 1;
    Integer limit = 2;
    Integer userId = 1;
    //fake object for output arg
    List<Run> runList = new ArrayList<Run>();
    new Expectations(){{
        entityManager.someMethodToMock(argumentMatchers);
        result = mockQuery;
        times = 1;
    //remaining expactations in your code, which will eventually return result
    }};

    //call method to test
    List<Run> result = runRepositoryService.findBySearchCriteria(searchCriteria, offset, limit, userId);

    //assertions
    assertEquals(runList, result);
}
}
Share:
10,041
stallion
Author by

stallion

Backend Software engineer at amazon by profession...

Updated on June 24, 2022

Comments

  • stallion
    stallion almost 2 years

    I am using spring-boot test with Mockito framework to test my application. One of the repository classes EntityManager as reference.

    My class looks like below.

        @Repository
        @Transactional
        @Slf4j
        public class SomeRepositoryService {
    
            @PersistenceContext
            private EntityManager entityManager;
    
            public List<Run> findBySearchCriteria(String searchCriteria,Integer 
     offset,Integer limit,Integer userId) {
            //code 
           }
        }
    

    And test class looks like :

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class RunRepositoryServiceTests {
    
        @MockBean
        EntityManager entityManager; 
    
    
        @Autowired
        private RunRepositoryService runRepositoryService;
    
        @Test
        public void testFindBySearchCriteria() {
    //code to test
        }
    }
    

    When i run this, i am getting

    Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.jpa.repository.support.DefaultJpaContext]: Constructor threw exception; nested exception is java.lang.NullPointerException
    
        Caused by: java.lang.NullPointerException: null
            at org.springframework.data.jpa.repository.support.DefaultJpaContext.<init>(DefaultJpaContext.java:53) ~[spring-data-jpa-2.0.9.RELEASE.jar:2.0.9.RELEASE]
    

    can anyone let me know how to test this or solve this issue?

  • stallion
    stallion over 5 years
    I tried it. It works, Thanks. But I will accept it if I don't get a Mockito based answer to this question.
  • stallion
    stallion over 5 years
    Tried with that.. I got this exception.. Caused by: java.lang.IllegalStateException: Failed to replace DataSource with an embedded database for tests. If you want an embedded database please put a supported one on the classpath or tune the replace attribute of @AutoConfigureTestDatabase.