无法在 Spring 启动测试中模拟持久性上下文



我正在使用带有Mockito框架的spring-boot测试来测试我的应用程序。存储库类之一 实体管理器 作为参考。

我的班级如下所示。

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

测试类看起来像:

@RunWith(SpringRunner.class)
@SpringBootTest
public class RunRepositoryServiceTests {
@MockBean
EntityManager entityManager; 

@Autowired
private RunRepositoryService runRepositoryService;
@Test
public void testFindBySearchCriteria() {
//code to test
}
}

当我运行这个时,我得到了

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]

任何人都可以让我知道如何测试或解决此问题吗?

你可以不用@DataJpaTest使用SpringRunner。 这对我有用:

@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();

}
}

我遇到了类似的问题,为了解决它,我不得不使用 Springs ReflectionTestUtils 来注入模拟:

@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(...);
....
}
}

您可以使用JMockit轻松模拟用@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);
}
}

您可以使用TestEntityManager而不是模拟:

@Autowired
private TestEntityManager entityManager;
@Autowired
private RunRepositoryService runRepositoryService;
@Test
public void testFindBySearchCriteria() {
// 1. Create needed objects and persist them using the test entity manager
// 2. Test your repository method
}

您还需要用@DataJpaTest注释您的测试以使其正常工作,请查看文档中的一些示例。

最新更新