कई प्लेटफार्मों के विपरीत, जावा कनेक्शन स्टब लाइब्रेरी की कमी से ग्रस्त है। यदि आप लंबे समय से इस दुनिया में हैं, तो आपको शायद वायरमॉक, बेटमैक्स या यहां तक कि स्पॉक से परिचित होना चाहिए। परीक्षणों में कई डेवलपर्स ऑब्जेक्ट के व्यवहार का वर्णन करने के लिए मॉकिटो का उपयोग करते हैं, DataJpaTest एक स्थानीय h2 डेटाबेस, ककड़ी परीक्षणों के साथ। आज आप एक हल्के विकल्प से मिलेंगे जो आपको विभिन्न समस्याओं से निपटने में मदद करेगा जो आपको इन तरीकों का उपयोग करके सामना कर सकते हैं। विशेष रूप से, anyStub निम्नलिखित समस्याओं को हल करने की कोशिश करता है:
- परीक्षण पर्यावरण विन्यास को सरल बनाएं
- परीक्षण के लिए डेटा संग्रह को स्वचालित करें
- अपने आवेदन के परीक्षण में रहें और किसी और चीज़ के परीक्षण से बचें
कोई भी स्टुब क्या है और कैसे काम करता है
AnyStub रैप फ़ंक्शन को कॉल करता है, जो पहले से रिकॉर्ड किए गए मिलान कॉल को खोजने की कोशिश कर रहा है। इसके साथ दो चीजें हो सकती हैं:
- यदि कोई मेल खाता है, तो कोई भी स्टॉस्ट उस कॉल से जुड़े रिकॉर्ड किए गए परिणाम को पुनर्स्थापित करेगा और उसे वापस करेगा
- यदि कोई मेल नहीं है और बाहरी सिस्टम तक पहुंच की अनुमति है, तो कोई भी व्यक्ति इस कॉल को करेगा, इस परिणाम को रिकॉर्ड करेगा और इसे वापस करेगा
बॉक्स से बाहर, किसी भी तरह http http के लिए अपाचे HttpClient से http क्लाइंट के लिए रैपर प्रदान करता है और javax.sql से कई इंटरफेस। DB कनेक्शन के लिए। आपको अन्य कनेक्शन के लिए स्टब्स बनाने के लिए एक एपीआई भी प्रदान किया जाता है।
AnyStub एक साधारण श्रेणी की लाइब्रेरी है और इसमें आपके पर्यावरण के विशेष विन्यास की आवश्यकता नहीं होती है। यह पुस्तकालय वसंत-बूट अनुप्रयोगों के साथ काम करने के उद्देश्य से है और आप इस मार्ग का अनुसरण करके अधिकतम लाभ प्राप्त करेंगे। आप इसे जावा के बाहर, सादे जावा अनुप्रयोगों में उपयोग कर सकते हैं, लेकिन निश्चित रूप से आपको अतिरिक्त काम करना होगा। निम्नलिखित विवरण वसंत-बूट अनुप्रयोगों के परीक्षण पर केंद्रित है।
चलो एकीकरण परीक्षण को देखें। यह आपके सिस्टम का परीक्षण करने का सबसे रोमांचक और व्यापक तरीका है। जब आप जादुई एनोटेशन लिखते हैं तो वास्तव में, स्प्रिंग-बूट और जुनीत आपके लिए लगभग सब कुछ करते हैं:
@RunWith(SpringRunner.class) @SpringBootTest
वर्तमान में, एकीकरण परीक्षणों को कम करके आंका जाता है और एक सीमित सीमा तक उपयोग किया जाता है, और कुछ डेवलपर्स उनसे बचते हैं। यह मुख्य रूप से समय लेने वाली तैयारी और परीक्षणों के रखरखाव या बिल्ड सर्वर पर पर्यावरण के विशेष कॉन्फ़िगरेशन की आवश्यकता के कारण है।
किसी भीStub के साथ, आपको वसंत-संदर्भ को अपंग करने की आवश्यकता नहीं है। इसके बजाय, संदर्भ को उत्पादन कॉन्फ़िगरेशन के करीब रखना सरल और सीधा है।
इस उदाहरण में, हम देखेंगे कि Pivotal से मैनुअल से किसी भी Stub को एक उपभोग्य वेब सेवा से कैसे जोड़ा जाए।
Pom.xml के माध्यम से लाइब्रेरी कनेक्ट करना
<dependency> <groupId>org.anystub</groupId> <artifactId>anystub</artifactId> <version>0.2.27</version> <scope>test</scope> </dependency>
अगला कदम वसंत संदर्भ को संशोधित करना है।
package hello; import org.anystub.http.StubHttpClient; import org.apache.http.client.HttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.client.RestTemplateCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @Configuration public class TestConfiguration { @Bean public RestTemplateBuilder builder() { RestTemplateCustomizer restTemplateCustomizer = new RestTemplateCustomizer() { @Override public void customize(RestTemplate restTemplate) { HttpClient real = HttpClientBuilder.create().build(); StubHttpClient stubHttpClient = new StubHttpClient(real); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setHttpClient(stubHttpClient); restTemplate.setRequestFactory(requestFactory); } }; return new RestTemplateBuilder(restTemplateCustomizer); } }
यह संशोधन अनुप्रयोग में घटक संबंधों को नहीं बदलता है, लेकिन केवल एक इंटरफ़ेस के कार्यान्वयन को बदलता है। यह हमें बारबरा लिस्क सबस्टीट्यूशन सिद्धांत के लिए भेजता है। यदि आपके एप्लिकेशन का डिज़ाइन इसका उल्लंघन नहीं करता है, तो यह प्रतिस्थापन कार्यक्षमता का उल्लंघन नहीं करेगा।
सब कुछ तैयार है। इस परियोजना में पहले से ही एक परीक्षण शामिल है।
@RunWith(SpringRunner.class) @SpringBootTest public class ApplicationTest { @Autowired private RestTemplate restTemplate; @Test public void contextLoads() { assertThat(restTemplate).isNotNull(); } }
यह परीक्षण खाली है, लेकिन यह पहले से ही आवेदन के संदर्भ में चल रहा है। मज़ा यहाँ से शुरू होता है । जैसा कि हमने ऊपर कहा, परीक्षण में अनुप्रयोग संदर्भ कार्य संदर्भ के साथ मेल खाता है जिसमें कमांडलाइनरनर बनाया गया है जिसमें बाहरी सिस्टम के लिए http अनुरोध निष्पादित किया गया है।
@SpringBootApplication public class Application { private static final Logger log = LoggerFactory.getLogger(Application.class); public static void main(String args[]) { SpringApplication.run(Application.class); } @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder.build(); } @Bean public CommandLineRunner run(RestTemplate restTemplate) throws Exception { return args -> { Quote quote = restTemplate.getForObject( "https://gturnquist-quoters.cfapps.io/api/random", Quote.class); log.info(quote.toString()); }; } }
यह पुस्तकालय के संचालन को प्रदर्शित करने के लिए पर्याप्त है। पहली बार परीक्षण शुरू करने के बाद, आपको नई complete/src/test/resources/anystub/stub.yml
।
request0: exception: [] keys: [GET, HTTP/1.1, 'https://gturnquist-quoters.cfapps.io/api/random'] values: [HTTP/1.1, '200', OK, 'Content-Type: application/json;charset=UTF-8', 'Date: Thu, 25 Apr 2019 23:04:49 GMT', 'X-Vcap-Request-Id: 5ffce9f3-d972-4e95-6b5c-f88f9b0ae29b', 'Content-Length: 177', 'Connection: keep-alive', '{"type":"success","value":{"id":3,"quote":"Spring has come quite a ways in addressing developer enjoyment and ease of use since the last time I built an application using it."}}']
क्या हुआ? स्प्रिंग-बूट ने एप्लिकेशन में परीक्षण कॉन्फ़िगरेशन से RestTemplateBuilder का निर्माण किया है। इसने http क्लाइंट के स्टब कार्यान्वयन के माध्यम से काम करने के लिए आवेदन का नेतृत्व किया। StubHttpClient ने अनुरोध को रोक दिया, स्टब फ़ाइल नहीं मिली, अनुरोध को निष्पादित किया, परिणाम को एक फ़ाइल में सहेजा, और फ़ाइल से पुनर्प्राप्त परिणाम वापस कर दिया।
अब से, आप इस परीक्षण को बिना इंटरनेट कनेक्शन के चला सकते हैं और यह अनुरोध सफल होगा। restTemplate.getForObject()
उसी परिणाम को लौटाएगा। आप अपने भविष्य के परीक्षणों में इस तथ्य पर भरोसा कर सकते हैं।
आप GitHub पर सभी वर्णित परिवर्तन पा सकते हैं।
वास्तव में, हमने अभी भी एक भी परीक्षण नहीं बनाया है। परीक्षण लिखने से पहले, आइए देखें कि यह डेटाबेस के साथ कैसे काम करता है।
इस उदाहरण में, हम Pivotal ट्यूटोरियल से स्प्रिंग के साथ JDBC का उपयोग करके रिलेशनल डेटा तक पहुँचने के लिए एक एकीकरण परीक्षण जोड़ेंगे।
इस मामले के लिए परीक्षण कॉन्फ़िगरेशन इस तरह दिखता है:
package hello; import org.anystub.jdbc.StubDataSource; import org.h2.jdbcx.JdbcDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @Configuration public class TestConfiguration { @Bean public DataSource dataSource() { JdbcDataSource ds = new JdbcDataSource(); ds.setURL("jdbc:h2:./test"); return new StubDataSource(ds); } }
यहां, एक बाहरी डेटाबेस के लिए एक नियमित डेटा स्रोत बनाया गया है और एक स्टब कार्यान्वयन के साथ लिपटा हुआ है - स्टबडाटासोर्स स्रोत। स्प्रिंग-बूट इसे संदर्भ में एम्बेड करता है। हमें परीक्षण में वसंत संदर्भ को चलाने के लिए कम से कम एक परीक्षण बनाने की भी आवश्यकता है।
package hello; import org.anystub.AnyStubId; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import static org.junit.Assert.*; @RunWith(SpringRunner.class) @SpringBootTest public class ApplicationTest { @Test @AnyStubId public void test() { } }
यह फिर से एक खाली परीक्षा है - इसका एकमात्र कार्य अनुप्रयोग संदर्भ को चलाना है। यहां हम एक बहुत महत्वपूर्ण एनोटेशन @AnystubId
देखते हैं, लेकिन यह अभी तक शामिल नहीं होगा।
पहले रन के बाद, आपको एक नया src/test/resources/anystub/stub.yml
जिसमें सभी डेटाबेस कॉल शामिल हैं। आपको आश्चर्य होगा कि वसंत कैसे डेटाबेस के साथ पर्दे के पीछे काम करता है। ध्यान दें कि, परीक्षण के नए रनों से डेटाबेस तक वास्तविक पहुंच नहीं होगी। यदि आप test.mv.db को हटाते हैं तो यह परीक्षणों के बार-बार चलने के बाद दिखाई नहीं देगा। परिवर्तन का पूरा सेट GitHub पर देखा जा सकता है ।
संक्षेप में देना। किसी भी साथ:
- आपको विशेष रूप से एक परीक्षण वातावरण स्थापित करने की आवश्यकता नहीं है
- परीक्षण वास्तविक डेटा के साथ किया जाता है
- परीक्षणों का पहला भाग आपकी मान्यताओं को साबित करता है और परीक्षण के डेटा को बचाता है, बाद वाले यह जांचते हैं कि सिस्टम में गिरावट नहीं हुई है
आपके पास शायद सवाल हैं: यह कवर कैसे करता है जहां डेटाबेस अभी तक मौजूद नहीं है, नकारात्मक परीक्षण और अपवाद से निपटने के लिए क्या करना है। हम इस पर लौट आएंगे, लेकिन पहले, हम सरल परीक्षण लिखने से निपटेंगे।
अब हम उपभोक्ता के साथ एक उपयोगी वेब सेवा का प्रयोग कर रहे हैं। इस परियोजना में ऐसे घटक शामिल नहीं हैं जिनका परीक्षण किया जा सकता है। दो कक्षाएं नीचे बनाई गई हैं, जो कुछ वास्तुकला डिजाइन की दो परतों को चित्रित करना चाहिए।
package hello; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; @Component public class DataProvider { private final RestTemplate restTemplate; public DataProvider(RestTemplate restTemplate) { this.restTemplate = restTemplate; } Quote provideData() { return restTemplate.getForObject( "https://gturnquist-quoters.cfapps.io/api/random", Quote.class); } }
DataProvider में डेटा तक पहुँच प्रदान करता है अस्थिर बाहरी व्यवस्था।
package hello; import org.springframework.stereotype.Component; @Component public class DataProcessor { private final DataProvider dataProvider; public DataProcessor(DataProvider dataProvider) { this.dataProvider = dataProvider; } int processData() { return dataProvider.provideData().getValue().getQuote().length(); } }
DataProcessor बाहरी सिस्टम से डेटा प्रोसेस करेगा।
हम DataProcessor
का परीक्षण करने का इरादा रखते हैं। प्रसंस्करण एल्गोरिथ्म की शुद्धता का परीक्षण करना और भविष्य के परिवर्तनों से प्रणाली को गिरावट से बचाने के लिए आवश्यक है।
इन लक्ष्यों को प्राप्त करने के लिए, आप डेटा सेट के साथ डेटाप्रोसेसर मॉक ऑब्जेक्ट बनाने और उसे परीक्षण में डेटाप्रोसेसर कंस्ट्रक्टर को पास करने पर विचार कर सकते हैं। एक अन्य तरीका उद्धरण वर्ग के प्रसंस्करण को उजागर करने के लिए डेटाप्रोसेसर को विघटित करना हो सकता है। फिर, इस तरह के एक वर्ग को यूनिट परीक्षणों का उपयोग करके परीक्षण करना आसान है (निश्चित रूप से, स्वच्छ कोड के बारे में सम्मानित पुस्तकों में यह अनुशंसित तरीका है)। आइए कोड परिवर्तन और परीक्षण डेटा के आविष्कार से बचने की कोशिश करें और सिर्फ एक परीक्षण लिखें।
@RunWith(SpringRunner.class) @SpringBootTest public class DataProcessorTest { @Autowired private DataProcessor dataProcessor; @Test @AnyStubId(filename = "stub") public void processDataTest() { assertEquals(131, dataProcessor.processData()); } }
@AnystubId एनोटेशन के बारे में बात करने का समय। यह एनोटेशन परीक्षणों में स्टब फ़ाइलों को प्रबंधित और नियंत्रित करने में मदद करता है। इसका उपयोग टेस्ट क्लास या इसकी विधि के साथ किया जा सकता है। यह एनोटेशन संबंधित क्षेत्र के लिए एक अलग स्टब फ़ाइल स्थापित करता है। यदि कोई क्षेत्र एक साथ वर्ग और विधि स्तर एनोटेशन द्वारा कवर किया जाता है, तो विधि एनोटेशन पूर्ववर्तीता लेता है। इस एनोटेशन में फ़ाइल नाम पैरामीटर है, जो स्टब फ़ाइल के नाम को परिभाषित करता है। एक्सटेंशन ".yml" स्वचालित रूप से जोड़ा जाता है यदि छोड़ा गया हो। इस परीक्षण को चलाने से आपको एक नई फ़ाइल नहीं मिलेगी। src/test/resources/anystub/stub.yml
पहले ही बनाई जा चुकी है और यह परीक्षण इसका पुन: उपयोग करेगा। क्वेरी के परिणाम का विश्लेषण करके हमें इस स्टब से 131 नंबर मिला है।
@Test @AnyStubId public void processDataTest2() { assertEquals(131, dataProcessor.processData()); Base base = getStub(); assertEquals(1, base.times("GET")); assertTrue(base.history().findFirst().get().matchEx_to(null, null, ".*gturnquist-quoters.cfapps.io.*")); }
इस परीक्षण में, फ़ाइल नाम पैरामीटर के बिना @AnyStubId एनोटेशन प्रकट होता है। इस स्थिति में, src/test/resources/anystubprocessDataTest2.yml
। फ़ाइल का नाम फ़ंक्शन (वर्ग) + ".yml" के नाम से बनाया गया है। एक बार जब कोई भी स्टस्ट इस परीक्षण के लिए एक नई फ़ाइल बनाता है तो आपको एक वास्तविक सिस्टम कॉल करने की आवश्यकता होती है। और यह हमारा सौभाग्य है कि नई बोली की लंबाई समान है। अंतिम दो चेक दिखाते हैं कि आवेदन के व्यवहार का परीक्षण कैसे किया जाए। यह आपके लिए उपलब्ध है: मापदंडों या मापदंडों के भागों द्वारा प्रश्नों का चयन करना और प्रश्नों की संख्या की गणना करना। समय और मैच फ़ंक्शंस के कई रूप हैं जो प्रलेखन में पाए जा सकते हैं।
@Test @AnyStubId(requestMode = RequestMode.rmTrack) public void processDataTest3() { assertEquals(79, dataProcessor.processData()); assertEquals(79, dataProcessor.processData()); assertEquals(168, dataProcessor.processData()); assertEquals(79, dataProcessor.processData()); Base base = getStub(); assertEquals(4, base.times("GET")); }
इस परीक्षण में, @AnyStubId नए requestMode पैरामीटर के साथ दिखाई देता है। यह आपको स्टब फ़ाइलों के लिए अनुमतियों को प्रबंधित करने की अनुमति देता है। नियंत्रण के लिए दो पहलू हैं: फ़ाइल खोज और बाहरी सिस्टम को कॉल करने की अनुमति।
RequestMode.rmTrack
निम्नलिखित नियमों को सेट करता है: यदि फ़ाइल अभी बनाई गई है, तो सभी अनुरोध बाहरी सिस्टम को भेजे जाते हैं और जवाब के साथ फाइल में लिखे जाते हैं, भले ही फ़ाइल में एक समान अनुरोध हो (फाइल में डुप्लिकेट की अनुमति है)। यदि परीक्षण चलाने से पहले स्टब फ़ाइल मौजूद है, तो बाहरी सिस्टम के अनुरोध निषिद्ध हैं। उसी क्रम में कॉल की उम्मीद की जाती है। यदि अगला अनुरोध फ़ाइल में अनुरोध से मेल नहीं खाता है, तो एक अपवाद फेंक दिया जाता है।
RequestMode.rmNew
यह मोड डिफ़ॉल्ट रूप से सक्रिय है। प्रत्येक अनुरोध को स्टब फ़ाइल में खोजा जाता है। यदि एक मिलान अनुरोध पाया जाता है - संबंधित परिणाम फ़ाइल से पुनर्स्थापित किया जाता है, तो बाहरी सिस्टम के लिए अनुरोध स्थगित कर दिया जाता है। यदि अनुरोध नहीं मिला है, तो बाहरी सिस्टम का अनुरोध किया जाता है, परिणाम एक फ़ाइल में सहेजा जाता है। फ़ाइल में डुप्लिकेट अनुरोध - घटित नहीं होते हैं।
RequestMode.rmNone
प्रत्येक अनुरोध को स्टब फ़ाइल में देखा जाता है। यदि एक मिलान क्वेरी पाई जाती है, तो इसका परिणाम फ़ाइल से पुनर्स्थापित किया जाता है। यदि परीक्षण एक अनुरोध उत्पन्न करता है जो फ़ाइल में नहीं है, तो एक अपवाद फेंक दिया जाता है।
पहले अनुरोध के पहले RequestMode.rmAll
, स्टब फ़ाइल साफ़ हो जाती है। सभी अनुरोध फ़ाइल को लिखे गए हैं (फ़ाइल में डुप्लिकेट अनुमत हैं)। यदि आप कनेक्शन का काम देखना चाहते हैं तो आप इस मोड का उपयोग कर सकते हैं।
RequestMode.rmPassThrough
सभी अनुरोधों को कार्यान्वयन स्टब को दरकिनार करते हुए सीधे बाहरी सिस्टम में भेजा जाता है।
ये परिवर्तन GitHub पर उपलब्ध हैं ।
और क्या?
हमने देखा कि कैसे किसी भी प्रतिक्रिया प्रतिक्रियाओं को बचाता है। यदि बाहरी सिस्टम का उपयोग करते समय एक अपवाद को फेंक दिया जाता है, तो कोई भी स्टस्टब इसे बचाएगा, और बाद के अनुरोधों पर इसे चलाएगा।
अक्सर अपवाद शीर्ष-स्तरीय कक्षाओं द्वारा फेंक दिए जाते हैं, जबकि कनेक्शन कक्षाएं एक वैध प्रतिक्रिया प्राप्त करती हैं (संभवतः एक त्रुटि कोड के साथ)। इस स्थिति में, कोई भी स्ट्रेस कोड के साथ बहुत ही उत्तर को पुन: प्रस्तुत करने के लिए जिम्मेदार है, और उच्च-स्तरीय कक्षाएं आपके परीक्षणों के अपवादों को भी फेंक देंगी।
भंडार में स्टब फ़ाइलें जोड़ें।
स्टब फ़ाइलों को हटाने और अधिलेखित करने से डरो मत।
स्टब फ़ाइलों को समझदारी से प्रबंधित करें। आप कई परीक्षणों में एक फ़ाइल का पुन: उपयोग कर सकते हैं या प्रत्येक परीक्षण के लिए एक व्यक्तिगत फ़ाइल प्रदान कर सकते हैं। अपनी आवश्यकताओं के लिए इस अवसर का उपयोग करें। लेकिन आमतौर पर अलग-अलग एक्सेस मोड के साथ सिंगल फाइल का उपयोग करना एक बुरा विचार है।
ये किसी भी स्टॉब की मुख्य विशेषताएं हैं।