मैं UserRepository
स्प्रिंग डेटा की मदद से एक रिपॉजिटरी (कहना ) चाहता हूं । मैं वसंत-डेटा (लेकिन वसंत के लिए नहीं) के लिए नया हूं और मैं इस ट्यूटोरियल का उपयोग करता हूं । डेटाबेस से निपटने के लिए प्रौद्योगिकियों की मेरी पसंद जेपीए 2.1 और हाइबरनेट है। समस्या यह है कि मैं इस तरह के भंडार के लिए इकाई परीक्षण कैसे लिखूं
create()
उदाहरण के लिए विधि लेते हैं । जैसा कि मैं परीक्षण-पहले काम कर रहा हूं, मैं इसके लिए एक इकाई परीक्षण लिखने वाला हूं - और यही मैं तीन समस्याओं से टकरा रहा हूं:
सबसे पहले, मैं
EntityManager
एकUserRepository
इंटरफ़ेस के गैर-मौजूदा कार्यान्वयन में एक नकली का इंजेक्शन कैसे लगाऊं ? स्प्रिंग डेटा इस इंटरफ़ेस के आधार पर एक कार्यान्वयन उत्पन्न करेगा:public interface UserRepository extends CrudRepository<User, Long> {}
हालांकि, मुझे नहीं पता कि इसे एक
EntityManager
मॉक और अन्य मॉक का उपयोग करने के लिए कैसे मजबूर किया जाए - अगर मैंने कार्यान्वयन खुद लिखा था, तो मेरे पास शायद एक सेटर विधि होगीEntityManager
, जिससे मुझे यूनिट परीक्षण के लिए अपने मॉक का उपयोग करने की अनुमति मिल सके। (वास्तविक डेटाबेस कनेक्टिविटी के लिए के रूप में, मैं एक हैJpaConfiguration
वर्ग, के साथ एनोटेट@Configuration
और@EnableJpaRepositories
है, जो प्रोग्राम के रूप में के लिए सेम को परिभाषित करता हैDataSource
,EntityManagerFactory
,EntityManager
आदि - लेकिन खजाने परीक्षण के अनुकूल हो सकता है और इन बातों को ओवरराइड करने के लिए अनुमति चाहिए)।दूसरा, क्या मुझे बातचीत के लिए परीक्षण करना चाहिए? मेरे लिए यह पता लगाना कठिन है कि किन विधियों को कहा जाता है
EntityManager
औरQuery
कहा जाना चाहिए (verify(entityManager).createNamedQuery(anyString()).getResultList();
क्योंकि वह उस पर लागू नहीं है)तीसरा, क्या मैं पहले स्थान पर स्प्रिंग-डेटा-जेनरेट किए गए तरीकों को यूनिट-टेस्ट करने वाला हूं? जैसा कि मैं जानता हूं, तीसरे पक्ष के पुस्तकालय कोड को यूनिट-परीक्षण करने वाला नहीं माना जाता है - केवल डेवलपर्स द्वारा लिखे गए कोड को ही यूनिट-परीक्षण किया जाना चाहिए। लेकिन अगर यह सच है, यह अभी भी पहले सवाल को फिर से दृश्य में लाता है: कहते हैं, मेरे पास मेरी रिपॉजिटरी के लिए कुछ कस्टम तरीके हैं, जिसके लिए मैं कार्यान्वयन लिखूंगा, मैं अपने मोज़ेक को कैसे
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