UserRepository
Spring Data의 도움으로 저장소 (예 :)를 만들고 싶습니다 . 나는 스프링 데이터에 익숙하지 않지만 (스프링은 아님)이 자습서를 사용합니다 . 데이터베이스를 다루기 위해 제가 선택한 기술은 JPA 2.1과 Hibernate입니다. 문제는 그러한 저장소에 대한 단위 테스트를 작성하는 방법에 대한 단서가 없다는 것입니다.
create()
예를 들어 방법을 보자 . 테스트를 먼저 할 때 단위 테스트를 작성해야합니다. 여기에서 세 가지 문제가 발생합니다.
먼저
EntityManager
존재하지 않는UserRepository
인터페이스 구현에 모의를 어떻게 주입 합니까? Spring Data는이 인터페이스를 기반으로 구현을 생성합니다.public interface UserRepository extends CrudRepository<User, Long> {}
그러나
EntityManager
모의 및 기타 모의 를 사용하도록 강제하는 방법을 모르겠습니다 . 구현을 직접 작성했다면에 대한 setter 메소드EntityManager
를 사용하여 단위 테스트에 모의를 사용할 수 있습니다. (실제 데이터베이스 연결에 관해서는, 나는이JpaConfiguration
주석 클래스@Configuration
와@EnableJpaRepositories
프로그램을 위해 콩을 정의,DataSource
,EntityManagerFactory
,EntityManager
등 -하지만 저장소 테스트 친화적 있어야하고,이 일을 오버라이드 (override)를 허용한다).둘째, 상호 작용을 테스트해야합니까? 내가 어떤 방법을 파악하는 것은 어렵다
EntityManager
및Query
(그와 유사한 호출로되어있다verify(entityManager).createNamedQuery(anyString()).getResultList();
)가 구현을 작성 누군지하지 않기 때문에.셋째, 스프링 데이터 생성 메소드를 먼저 테스트해야합니까? 아시다시피, 타사 라이브러리 코드는 단위 테스트를 거치지 않아야합니다. 개발자가 직접 작성한 코드 만 단위 테스트를 거쳐야합니다. 나는 내 망신 시켰습니다 주사 I을 어떻게,하는 I 구현을 작성하는 것, 내 저장소에 대한 사용자 지정 방법의 몇 가지있다 말 : 그게 사실이라면, 그것은 여전히 첫 번째 질문의 장면에 등을 제공
EntityManager
하고Query
생성 마지막으로, 저장소?
참고 : 통합 및 단위 테스트 를 모두 사용하여 리포지토리를 테스트합니다. 통합 테스트를 위해 HSQL 인 메모리 데이터베이스를 사용하고 있으며 단위 테스트에 데이터베이스를 사용하고 있지 않습니다.
그리고 아마도 네 번째 질문은 통합 테스트에서 올바른 객체 그래프 생성 및 객체 그래프 검색을 테스트하는 것이 맞습니까?
업데이트 : 오늘 모의 주입 실험을 계속했습니다. 모의 주입을 허용하는 정적 내부 클래스를 만들었습니다.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@Transactional
@TransactionConfiguration(defaultRollback = true)
public class UserRepositoryTest {
@Configuration
@EnableJpaRepositories(basePackages = "com.anything.repository")
static class TestConfiguration {
@Bean
public EntityManagerFactory entityManagerFactory() {
return mock(EntityManagerFactory.class);
}
@Bean
public EntityManager entityManager() {
EntityManager entityManagerMock = mock(EntityManager.class);
//when(entityManagerMock.getMetamodel()).thenReturn(mock(Metamodel.class));
when(entityManagerMock.getMetamodel()).thenReturn(mock(MetamodelImpl.class));
return entityManagerMock;
}
@Bean
public PlatformTransactionManager transactionManager() {
return mock(JpaTransactionManager.class);
}
}
@Autowired
private UserRepository userRepository;
@Autowired
private EntityManager entityManager;
@Test
public void shouldSaveUser() {
User user = new UserBuilder().build();
userRepository.save(user);
verify(entityManager.createNamedQuery(anyString()).executeUpdate());
}
}
그러나이 테스트를 실행하면 다음과 같은 스택 추적이 제공됩니다.
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:101)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:319)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:212)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:232)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:175)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:77)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'entityManager' threw exception; nested exception is java.lang.IllegalArgumentException: JPA Metamodel must not be null!
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1493)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1197)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:684)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:121)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:250)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91)
... 28 more
Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'entityManager' threw exception; nested exception is java.lang.IllegalArgumentException: JPA Metamodel must not be null!
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:108)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:62)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1489)
... 44 more