मेरे पास निम्न विधि है:

public async Task ScrapeObjects(int page)
{
    try
    {
        while (!isObjectSearchCompleted)
        {
            UriBuilder builder = new UriBuilder(_apiSettings.Value.FundaUrl)
            {
                Query = $"test"
            };
            var result = await _apiCaller.GetResponseAsync<ResponseModel>(builder.Uri).ConfigureAwait(false);
            Thread.Sleep(TimeSpan.FromSeconds(1));

            if (result != null)
            {
                foreach (var obj in result.Objects)
                {
                    UpdateDictionary(propertiesAmount, obj.name);
                }
            }
            if (!fundaResult.Objects.Any())
            {
                isObjectSearchCompleted = true;
            }
            else
            {
                page++;
            }
        }
    }
    catch (HttpRequestException ex)
    {
        if (ex.Message == "Request limit exceeded.")
        {
            Thread.Sleep(TimeSpan.FromSeconds(60));
            ScrapeObjects(page);
        }
        Log.Fatal(ex, ex.Message);
    }
}

मैं इसे यूनिट टेस्ट करने की कोशिश कर रहा हूं। हालांकि यह एक लंबी चलने वाली प्रक्रिया है। मेरा _apiCaller पर नियंत्रण है क्योंकि मैं इसका मजाक उड़ा रहा हूं। मैं जो करने की कोशिश कर रहा हूं वह निम्नलिखित 2 परिदृश्यों का परीक्षण कर रहा है:

1) _apiCaller पहली बार सही परिणाम देता है। मेरा शब्दकोश अपडेट डिक्शनरी के माध्यम से अपडेट किया जाता है। दूसरी कॉल इसके बजाय कोई परिणाम नहीं देती है और इसलिए पूरी विधि अपने अंत तक पहुँच जाती है। मेरे परीक्षण का लक्ष्य यह सुनिश्चित करना है कि मेरा शब्दकोश अद्यतन किया गया है।

या

2) _apiCaller पहली बार सही परिणाम देता है। मेरा शब्दकोश अपडेट डिक्शनरी के माध्यम से अपडेट किया जाता है। दूसरी कॉल इसके बजाय एक अपवाद फेंकता है और मेरी विधि समाप्त हो जाती है। मेरे परीक्षण का लक्ष्य यह सुनिश्चित करना है कि मेरा शब्दकोश अद्यतन किया गया है।

दोनों ही मामलों में मुझे फ्लाई पर या कम से कम पहली बार इसे कॉल करने के बाद मेरी विधि (मेरे नकली _apiCaller) के व्यवहार को बदलने की जरूरत है। इसे कैसे प्राप्त किया जा सकता है? अग्रिम में धन्यवाद!

1
Tarta 21 मार्च 2020, 20:25

1 उत्तर

सबसे बढ़िया उत्तर

उपयोग किए जाने पर नकली के व्यवहार को समायोजित करने के लिए SetupSequence का उपयोग करें।

1) _apiCaller पहली बार सही परिणाम देता है। मेरा शब्दकोश UpdateDictionary के माध्यम से अद्यतन किया जाता है। दूसरी कॉल इसके बजाय कोई परिणाम नहीं देती है और इसलिए पूरी विधि अपने अंत तक पहुँच जाती है। मेरे परीक्षण का लक्ष्य यह सुनिश्चित करना है कि मेरा शब्दकोश अद्यतन किया गया है।

apiMock.SetupSequence(_ => _.GetResponseAsync<ResponseModel>(It.IsAny<Uri>()))
    .Returns(Task.FromResult(correctResponseModel)) // returns the correct result the first time.
    .Returns(Task.FromResult((ResponseModel)null)); // The second call instead returns no result

2) _apiCaller पहली बार सही परिणाम देता है। मेरा शब्दकोश UpdateDictionary के माध्यम से अद्यतन किया जाता है। दूसरी कॉल इसके बजाय एक अपवाद फेंकता है और मेरी विधि समाप्त हो जाती है। मेरे परीक्षण का लक्ष्य यह सुनिश्चित करना है कि मेरा शब्दकोश अद्यतन किया गया है।

apiMock.SetupSequence(_ => _.GetResponseAsync<ResponseModel>(It.IsAny<Uri>()))
    .Returns(Task.FromResult(correctResponseModel)) // returns the correct result the first time.
    .Throws(new HttpRequestException("Request limit exceeded.")); //second call throws an exception

उस ने कहा, async-await को Thread.Sleep के साथ न मिलाएं Task.Delay का प्रयोग करें

await Task.Delay(TimeSpan.FromSeconds(1));

//...

आप अपने आप को catch में अवांछित व्यवहार खोल रहे हैं क्योंकि पुनः प्रयास कॉल की प्रतीक्षा नहीं की जा रही है।

catch (HttpRequestException ex)
{
    if (ex.Message == "Request limit exceeded.")
    {
        Thread.Sleep(TimeSpan.FromSeconds(60));
        ScrapeObjects(page); //<-- not awaited.
    }
    Log.Fatal(ex, ex.Message);
}

मैं आपके डिजाइन में उस परिदृश्य को बेहतर ढंग से संभालने के लिए पुन: प्रयास पैटर्न पर शोध करने का सुझाव दूंगा

1
Nkosi 22 मार्च 2020, 01:02