2013-06-27 9 views
105

दौरान मैं एक साधारण सेम है कि रूपों को मान्य करने के लिए अपने कार्यक्रम में प्रयुक्त के लिए एक यूनिट टेस्ट लिखने की कोशिश कर रहा हूँ। सेम @Component साथ एनोटेट और एक वर्ग चर का उपयोग कर आरंभ नहीं हो जाता है @Value("${this.property.value}") private String thisProperty;को आबाद करने स्प्रिंग @value यूनिट टेस्ट

मैं इस वर्ग के भीतर मान्यता तरीकों के लिए इकाई परीक्षण लिखने के लिए, तथापि, यदि संभव हो तो मैं ऐसा करने के लिए चाहते हैं का उपयोग गुण फ़ाइल के बिना चाहते हैं । इसके पीछे मेरा तर्क यह है कि यदि मैं गुण फ़ाइल से बदल रहा हूं, तो मैं अपने परीक्षण मामले को प्रभावित नहीं करना चाहता हूं। मेरा टेस्ट केस उस कोड का परीक्षण कर रहा है जो मूल्य को मान्य करता है, न कि मूल्य।

वहाँ एक जावा वर्ग को प्रारंभ और स्प्रिंग @value संपत्ति है कि वर्ग के अंदर पॉप्युलेट करने के लिए अपने परीक्षण वर्ग के अंदर जावा कोड का उपयोग करने के तो का उपयोग करने वाले के साथ परीक्षण करने के लिए एक तरीका है?

मैं इस How To कि करीब हो रहा है मिला है, लेकिन अभी भी एक गुण फ़ाइल का उपयोग करता है। मैं बल्कि यह जावा कोड होगा।

धन्यवाद

उत्तर

88

यदि संभव हो तो मैं वसंत संदर्भ के बिना उन परीक्षण लिखने के लिए कोशिश करेंगे। यदि आप इस कक्षा को वसंत के बिना अपने परीक्षण में बनाते हैं, तो आपके खेतों पर पूरा नियंत्रण होता है।

@value फ़ील्ड सेट करने के लिए आप स्प्रिंग्स ReflectionTestUtils का उपयोग कर सकते हैं - इसमें निजी फ़ील्ड सेट करने के लिए setField विधि है।

@see JavaDoc: ReflectionTestUtils.setField(java.lang.Object, java.lang.String, java.lang.Object)

+1

वास्तव में मैं क्या करने की कोशिश कर रहा था और क्या मैं अपने वर्ग के अंदर मान सेट करने के लिए देख रहा था, धन्यवाद! – Kyle

+1

या यहां तक ​​कि वसंत निर्भरताओं के बिना भी क्षेत्र को डिफ़ॉल्ट पहुंच (पैकेज संरक्षित) में बदलकर परीक्षण के लिए इसे सुलभ बनाने के लिए। –

+2

उदाहरण: 'org.springframework.test.util.ReflectionTestUtils.setField (classUnderTest," फ़ील्ड "," मान ");' – Olivier

36

यदि आप चाहते हैं, आप अब भी वसंत संदर्भ के भीतर अपने परीक्षण चलाने और स्प्रिंग विन्यास वर्ग के भीतर आवश्यक गुण सेट कर सकते हैं। आप JUnit उपयोग करते हैं, SpringJUnit4ClassRunner का उपयोग करें और इस तरह अपने परीक्षण के लिए समर्पित विन्यास वर्ग को परिभाषित:

वर्ग परीक्षण के अंतर्गत:

@Component 
public SomeClass { 

    @Autowired 
    private SomeDependency someDependency; 

    @Value("${someProperty}") 
    private String someProperty; 
} 

परीक्षण वर्ग:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = SomeClassTestsConfig.class) 
public class SomeClassTests { 

    @Autowired 
    private SomeClass someClass; 

    @Autowired 
    private SomeDependency someDependency; 

    @Before 
    public void setup() { 
     Mockito.reset(someDependency); 

    @Test 
    public void someTest() { ... } 
} 

और के लिए विन्यास वर्ग यह परीक्षण:

@Configuration 
public class SomeClassTestsConfig { 

    @Bean 
    public static PropertySourcesPlaceholderConfigurer properties() throws Exception { 
     final PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer(); 
     Properties properties = new Properties(); 

     properties.setProperty("someProperty", "testValue"); 

     pspc.setProperties(properties); 
     return pspc; 
    } 
    @Bean 
    public SomeClass getSomeClass() { 
     return new SomeClass(); 
    } 

    @Bean 
    public SomeDependency getSomeDependency() { 
     // Mockito used here for mocking dependency 
     return Mockito.mock(SomeDependency.class); 
    } 
} 

ऐसा करने के बाद, मैं अनुशंसा नहीं करता इस दृष्टिकोण, मैंने इसे संदर्भ के लिए यहां जोड़ा है। मेरी राय में मॉकिटो धावक का उपयोग करना बहुत बेहतर तरीका है। उस स्थिति में आप वसंत के अंदर परीक्षण नहीं चलाते हैं, जो कि अधिक स्पष्ट और सरल है।

+2

मैं मानता हूं कि अधिकांश तर्कों का परीक्षण मॉकिटो के साथ किया जाना चाहिए। मेरी इच्छा है कि स्प्रिंग के माध्यम से परीक्षण चलाने की तुलना में एनोटेशन की उपस्थिति और शुद्धता का परीक्षण करने का एक बेहतर तरीका था। – Altair7852

15

यह काम करने के लिए लगता है, हालांकि अभी भी एक सा वर्बोज़ (मैं अभी भी कुछ कम करना चाहते हैं):

@BeforeClass 
public static void beforeClass() { 
    System.setProperty("some.property", "<value>"); 
} 

// Optionally: 
@AfterClass 
public static void afterClass() { 
    System.clearProperty("some.property"); 
} 
+0

मुझे लगता है कि यह उत्तर साफ़ है क्योंकि यह वसंत अज्ञेयवादी है, यह विभिन्न परिदृश्यों के लिए अच्छी तरह से काम करता है, जैसे कि जब आप कस्टम टेस्ट धावक का उपयोग करना चाहते हैं और केवल '@ टेस्टप्रोपर्टी' एनोटेशन नहीं जोड़ सकते हैं। – raspacorp

4

विन्यास में PropertyPlaceholderConfigurer जोड़ा जा रहा है मेरे लिए काम कर रहा है।

@Configuration 
@ComponentScan 
@EnableJpaRepositories 
@EnableTransactionManagement 
public class TestConfiguration { 
@Bean 
public DataSource dataSource() { 
    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); 
    builder.setType(EmbeddedDatabaseType.DERBY); 
    return builder.build(); 
} 

@Bean 
public LocalContainerEntityManagerFactoryBean entityManagerFactory() { 
    LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); 
    entityManagerFactoryBean.setDataSource(dataSource()); 
    entityManagerFactoryBean.setPackagesToScan(new String[] { "com.test.model" }); 
    // Use hibernate 
    JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
    entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter); 
    entityManagerFactoryBean.setJpaProperties(getHibernateProperties()); 
    return entityManagerFactoryBean; 
} 

private Properties getHibernateProperties() { 
    Properties properties = new Properties(); 
    properties.put("hibernate.show_sql", "false"); 
    properties.put("hibernate.dialect", "org.hibernate.dialect.DerbyDialect"); 
    properties.put("hibernate.hbm2ddl.auto", "update"); 
    return properties; 
} 

@Bean 
public JpaTransactionManager transactionManager() { 
    JpaTransactionManager transactionManager = new JpaTransactionManager(); 
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); 
    return transactionManager; 
} 

@Bean 
PropertyPlaceholderConfigurer propConfig() { 
    PropertyPlaceholderConfigurer placeholderConfigurer = new PropertyPlaceholderConfigurer(); 
    placeholderConfigurer.setLocation(new ClassPathResource("application_test.properties")); 
    return placeholderConfigurer; 
} 

}

और परीक्षण वर्ग

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = TestConfiguration.class) 
public class DataServiceTest { 

@Autowired 
private DataService dataService; 

@Autowired 
private DataRepository dataRepository; 

@Value("${Api.url}") 
private String baseUrl; 

@Test 
public void testUpdateData() { 
    List<Data> datas = (List<Data>) dataRepository.findAll(); 
    assertTrue(datas.isEmpty()); 
    dataService.updateDatas(); 
    datas = (List<Data>) dataRepository.findAll(); 
    assertFalse(datas.isEmpty()); 
} 

}

57

स्प्रिंग 4 के बाद से में।1 आप यूनिट टेस्ट क्लास स्तर पर org.springframework.test.context.TestPropertySource एनोटेशन का उपयोग कर कोड में केवल संपत्ति मान सेट कर सकते हैं। यह वसंत संदर्भ में org.springframework.context.support.PropertySourcesPlaceholderConfigurer के कहने के लिए आवश्यक है

संपादित 24-08-: तुम भी निर्भर सेम उदाहरणों

उदाहरण के लिए

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = FooTest.Config.class) 
@TestPropertySource(properties = { 
    "some.bar.value=testValue", 
}) 
public class FooTest { 

    @Value("${some.bar.value}") 
    String bar; 

    @Test 
    public void testValueSetup() { 
    assertEquals("testValue", bar); 
    } 


    @Configuration 
    static class Config { 

    @Bean 
    public static PropertySourcesPlaceholderConfigurer propertiesResolver() { 
     return new PropertySourcesPlaceholderConfigurer(); 
    } 

    } 

} 

नोट में गुण इंजेक्शन लगाने के लिए इस दृष्टिकोण का उपयोग कर सकता है 2017: यदि आप स्प्रिंगबूट 1.4.0 का उपयोग कर रहे हैं और बाद में आप @SpringBootTest और @SpringBootConfiguration एनोटेशन के साथ परीक्षण शुरू कर सकते हैं। अधिक जानकारी here

SpringBoot के मामले में हम कोड निम्नलिखित है

@SpringBootTest 
@SpringBootConfiguration 
@RunWith(SpringJUnit4ClassRunner.class) 
@TestPropertySource(properties = { 
    "some.bar.value=testValue", 
}) 
public class FooTest { 

    @Value("${some.bar.value}") 
    String bar; 

    @Test 
    public void testValueSetup() { 
    assertEquals("testValue", bar); 
    } 

} 
+0

धन्यवाद, आखिरकार किसी ने जवाब दिया कि कैसे मूल्य ओवरराइड करें और फ़ील्ड कैसे सेट करें। मैं PostConstruct में स्ट्रिंग फ़ील्ड से मान प्राप्त करता हूं और इसलिए मुझे स्प्रिंग द्वारा निर्धारित स्ट्रिंग मान की आवश्यकता होती है, निर्माण के बाद नहीं। – tequilacat

+0

मुझे मदद करने में खुशी है –

संबंधित मुद्दे