2015-06-08 7 views
9

चलो कहते हैं कि मैं एक बाकी सेवा ए बदले में यह सेवा एक और बाकी सेवा बी हिट और यूआरआई बाकी पर हिट करने के लिए की एक सूची हो जाता है के लिए वसंत एकीकरण परीक्षणों लिख रहा हूँ चलो निपटने सेवा सी। यह एक तरह का ऑटो-खोज पैटर्न है। मैं MockRestServiceServer का उपयोग कर बी और सी प्रतिक्रियाओं का नकल करना चाहता हूं।
अब बी से प्रतिक्रिया यूआरआई की एक सूची है, वे सब बहुत समान हैं, और उदाहरण के लिए मान लीजिए कि बी से मेरी प्रतिक्रिया इतनी तरह है:स्प्रिंग MockRestServiceServer उसी URI (स्वत: खोज) के लिए एक से अधिक अनुरोध

{ 
    uris: ["/stuff/1.json", "/stuff/2.json", "/stuff/39.json", "/stuff/47.json"] 
} 

बस सेवा के एक से प्रत्येक में संलग्न कर देगा उन्हें सेवा सी के लिए आधार यूआरएल पर और उन अनुरोधों को बनाते हैं।
मॉकिंग बी आसान है क्योंकि यह केवल 1 अनुरोध है।
मजाक सी एक परेशानी के रूप में मैं नकली प्रतिक्रिया उचित हर एक यूआरआई नकली करने के लिए होता है। मैं इसे स्वचालित करना चाहता हूँ!
तो सबसे पहले मैं लिखने के अपने खुद के मेल खाने वाला एक पूर्ण URL नहीं मैच के लिए, लेकिन यह का हिस्सा:

public class RequestContainsUriMatcher implements RequestMatcher { 
    private final String uri; 

    public RequestContainsUriMatcher(String uri){ 
     this.uri = uri; 
    } 

    @Override 
    public void match(ClientHttpRequest clientHttpRequest) throws IOException, AssertionError { 
     assertTrue(clientHttpRequest.getURI().contains(uri)); 
    } 
} 

यह ठीक काम करता है के रूप में अब मैं यह कर सकता:

public RequestMatcher requestContainsUri(String uri) { 
    return new RequestContainsUriMatcher(uri); 
} 

MockRestServiceServer.createServer(restTemplate) 
      .expect(requestContainsUri("/stuff")) 
      .andExpect(method(HttpMethod.GET)) 
      .andRespond(/* I will get to response creator */); 

अब सभी की आवश्यकता है एक प्रतिक्रिया निर्माता है कि पूरा अनुरोध URL जानता है और जहां नकली डेटा बैठता है (मैं इसे परीक्षण संसाधन फ़ोल्डर में json फ़ाइलों के रूप में होगा):

public class AutoDiscoveryCannedDataResponseCreator implements ResponseCreator { 
    private final Function<String, String> cannedDataBuilder; 

    public AutoDiscoveryCannedDataResponseCreator(Function<String, String> cannedDataBuilder) { 
     this.cannedDataBuilder = cannedDataBuilder; 
    } 

    @Override 
    public ClientHttpResponse createResponse(ClientHttpRequest clientHttpRequest) throws IOException { 
     return withSuccess(cannedDataBuilder.apply(requestUri), MediaType.APPLICATION_JSON) 
        .createResponse(clientHttpRequest); 
    } 
} 

अब सामान के लिए आसान है, मैं हवलदार ई एक निर्माता को लिखने के लिए जो एक स्ट्रिंग के रूप में यूआरआई अनुरोध करता है और एक स्ट्रिंग के रूप में नकली डेटा देता है! प्रतिभाशाली!

public ResponseCreator withAutoDetectedCannedData() { 
    Function<String, String> cannedDataBuilder = new Function<String, String>() { 
     @Override 
     public String apply(String requestUri) { 
      //logic to get the canned data based on URI 
      return cannedData; 
     } 
    }; 

    return new AutoDiscoveryCannedDataResponseCreator(cannedDataBuilder); 
} 

MockRestServiceServer.createServer(restTemplate) 
      .expect(requestContainsUri("/stuff")) 
      .andExpect(method(HttpMethod.GET)) 
      .andRespond(withAutoDetectedCannedData()); 

यह ठीक काम करता है! .... पहले अनुरोध के लिए।
पहले अनुरोध (/stuff/1.json) मेरी MockRestServiceServer संदेश के साथ प्रतिक्रिया के बाद "अभिकथन त्रुटि: आगे कोई उम्मीद अनुरोध"।
मूल रूप से, मुझे लगता है कि MockRestServiceServer के रूप में कई अनुरोधों के रूप में वहाँ .expect थे बना सकते हैं() उस पर कॉल करता है। और चूंकि मेरे पास उनमें से केवल 1 था, केवल पहला अनुरोध ही होगा।
क्या इसके आसपास कोई रास्ता है? मैं वास्तव में सेवा सी 10 या 20 बार ...

+0

RequestContainsUriMatcher कार्यान्वयन – Silentbang

उत्तर

14

आप MockRestServiceServer वर्ग को देखें, तो यह दो 'की उम्मीद()' के तरीकों का समर्थन करता है। '() ExpectedCount.once' लेकिन दूसरी विधि करने के लिए पहली चूक आप यह मान

public ResponseActions expect(RequestMatcher matcher) { 
    return this.expect(ExpectedCount.once(), matcher); 
} 

public ResponseActions expect(ExpectedCount count, RequestMatcher matcher) { 
    return this.expectationManager.expectRequest(count, matcher); 
} 

मैं इस टिकट MockRestServiceServer should allow for an expectation to occur multiple times जो दूसरी विधि के लिए कुछ विकल्प की रूपरेखा पाया बदलने की अनुमति देता है।

आपके मामले में मैं स्थिर आयात जोड़ने और manyTimes का उपयोग कर लगता है कि() विधि पाश के लिए से neater कोड है

ckRestServiceServer 
      .expect(manyTimes(), requestContainsUri("/stuff")) 
      .andExpect(method(HttpMethod.GET)) 

अन्य विकल्प

once(); 
manyTimes(); 
times(5); 
min(2); 
max(8); 
between(3,6); 
+2

वसंत 4.3 – aurelije

+1

में कार्यान्वित यह अब सही उत्तर है और इसे इस तरह चुना जाना चाहिए। –

8

संपादित उपहास करने के लिए नहीं करना चाहते हैं: जो वसंत 4.3+ उपयोगकर्ताओं के लिए सही समाधान से पता चलता @emeraldjava से उत्तर देखें।

दुर्भाग्य से कोई भी अच्छा तंत्र एकाधिक कॉल की अपेक्षा करने के लिए नहीं है। आप या तो इसे मैन्युअल रूप से करना या छोरों का उपयोग, उदा .:

for (int i = 0; i < 10; i++) {   
     mockRestServiceServer 
       .expect(requestContainsUri("/stuff")) 
       .andExpect(method(HttpMethod.GET)) 
       .andRespond(withAutoDetectedCannedData()); 
} 

ध्यान रखें कि अनुरोध बुलाया जाना चाहिए किसी भी रुकावट के बिना, उदा एक और आरईएसटी कॉल नहीं हो सकता है जो "/ सामान" यूआरआई से मेल नहीं खाता है।

+0

पाश के लिए धन्यवाद कर रहे हैं इसे हल करता है धन्यवाद – Silentbang

+0

एक बार उम्मीद की जा रही है तो आप अतिरिक्त उम्मीदों को जोड़ नहीं सकते हैं। 'पहले से चल रहे परीक्षण के साथ अधिक अपेक्षित अनुरोध नहीं जोड़ सकते हैं –

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