ইউনিট পরীক্ষার জন্য একটি অ্যাসিঙ্ক্রোনাস পদ্ধতি উপহাস করার জন্য Moq ব্যবহার করা


178

আমি একটি সেবার জন্য একটি পদ্ধতি যা ওয়েব করে তোলে তা পরীক্ষা করছি API কল করে তা পরীক্ষা করছি। HttpClientআমি যদি স্থানীয়ভাবে ওয়েব সার্ভিস (সমাধানে অন্য কোনও প্রকল্পে অবস্থিত) চালাই তবে ইউনিট পরীক্ষার জন্য একটি সাধারণ কাজ করে ।

তবে আমি যখন আমার পরিবর্তনগুলি যাচাই করি তখন বিল্ড সার্ভারটির ওয়েব পরিষেবায় অ্যাক্সেস থাকবে না তাই পরীক্ষাগুলি ব্যর্থ হবে।

আমি আমার ইউনিট পরীক্ষার জন্য একটি IHttpClientইন্টারফেস তৈরি করে এবং আমার অ্যাপ্লিকেশনটিতে আমি ব্যবহার করি এমন একটি সংস্করণ প্রয়োগ করে এটির জন্য একটি উপায় তৈরি করেছি । ইউনিট পরীক্ষাগুলির জন্য, আমি একটি বিদ্রূপযুক্ত অ্যাসিঙ্ক্রোনাস পোস্ট পদ্ধতিটি সহ একটি উপহাস সংস্করণ তৈরি করি। এখানেই আমি সমস্যার মধ্যে পড়েছি। আমি HttpStatusResultএই বিশেষ পরীক্ষার জন্য একটি ঠিক ফিরিয়ে দিতে চাই । অন্য অনুরূপ পরীক্ষার জন্য আমি একটি খারাপ ফলাফল ফিরে আসব।

পরীক্ষা চলবে তবে কখনই শেষ হবে না। এটি অপেক্ষা করে। আমি অ্যাসিক্রোনাস প্রোগ্রামিং, ডেলিগেটস এবং নিজেই মোকের কাছে নতুন এবং আমি নতুন জিনিস শিখার জন্য কিছু সময়ের জন্য এসও এবং গুগল অনুসন্ধান করেছিলাম তবে এখনও আমি এই সমস্যাটি পেরেছি বলে মনে হয় না।

এখানে আমি যে পদ্ধতিটি পরীক্ষা করার চেষ্টা করছি তা এখানে:

public async Task<bool> QueueNotificationAsync(IHttpClient client, Email email)
{
    // do stuff
    try
    {
        // The test hangs here, never returning
        HttpResponseMessage response = await client.PostAsync(uri, content);

        // more logic here
    }
    // more stuff
}

এখানে আমার ইউনিট পরীক্ষা পদ্ধতি:

[TestMethod]
public async Task QueueNotificationAsync_Completes_With_ValidEmail()
{
    Email email = new Email()
    {
        FromAddress = "bob@example.com",
        ToAddress = "bill@example.com",
        CCAddress = "brian@example.com",
        BCCAddress = "ben@example.com",
        Subject = "Hello",
        Body = "Hello World."
    };
    var mockClient = new Mock<IHttpClient>();
    mockClient.Setup(c => c.PostAsync(
        It.IsAny<Uri>(),
        It.IsAny<HttpContent>()
        )).Returns(() => new Task<HttpResponseMessage>(() => new HttpResponseMessage(System.Net.HttpStatusCode.OK)));

    bool result = await _notificationRequestService.QueueNotificationAsync(mockClient.Object, email);

    Assert.IsTrue(result, "Queue failed.");
}

আমি কি ভুল করছি?

আপনার সাহায্যের জন্য ধন্যবাদ।

উত্তর:


348

আপনি একটি কাজ তৈরি করছেন তবে এটি কখনও শুরু করেন না, সুতরাং এটি কখনই শেষ হয় না। তবে, কেবল টাস্কটি শুরু করবেন না - পরিবর্তে, ব্যবহারটি পরিবর্তন করুন Task.FromResult<TResult>যা আপনাকে ইতিমধ্যে সম্পন্ন একটি টাস্ক দেবে:

...
.Returns(Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.OK)));

মনে রাখবেন যে আপনি প্রকৃত অ্যাসিনক্রোনাই এইভাবে পরীক্ষা করবেন না - আপনি যদি এটি করতে চান তবে আপনাকে Task<T>আরও সূক্ষ্ম পদ্ধতিতে নিয়ন্ত্রণ করতে পারেন এমনটি তৈরি করতে আপনাকে আরও কিছু কাজ করতে হবে ... তবে এটি এমন কিছু অন্য দিন.

আপনি IHttpClientসমস্ত কিছুকে উপহাস করার পরিবর্তে একটি জাল ব্যবহার করার বিষয়টি বিবেচনা করতেও পারেন - এটি আপনাকে কতবার প্রয়োজন তা নির্ভর করে।


2
আপনাকে অনেক ধন্যবাদ. এটা দুর্দান্ত কাজ করেছে। আমি অনুভব করলাম এটি সম্ভবত এমন কিছু সহজ যা আমি বুঝতে পারি নি।
mvanella

2
পুনরায়: নকল আইএইচটিপিপ্লায়েন্ট, আমি এটি বিবেচনা করেছি তবে ওয়েব এপিআই থেকে প্রত্যাশিত আচরণের উপর ভিত্তি করে বিভিন্ন পরীক্ষার জন্য আমার আলাদা আলাদা এইচটিপিস্ট্যাটাসকোডগুলি ফিরিয়ে আনতে সক্ষম হওয়া দরকার এবং এটি আমাকে আরও নিয়ন্ত্রণ দেয় বলে মনে হয়েছিল।
mvanella

3
@ এমওয়ানেলা: হ্যাঁ, তাই আপনি এমন একটি জাল তৈরি করতে চান যা আপনি যা চান তা ফিরে আসতে পারে। চিন্তা করার মতো কিছু।
জন স্কিটি

133
যে কেউ এখন এটি সন্ধান করে তাদের জন্য, এমকিউ ৪.২ এর একটি এক্সটেনশন ডাকা হয়েছে ReturnsAysnc, যা ঠিক এটি করে।
স্টুয়ার্ট গ্র্যাসি

3
@ লিগ্যাসিবাস আমি এর জন্য কোনও ডকুমেন্টেশনের লিঙ্ক খুঁজে পাই না, যদিও এপিআই ডক্স বলছে যে তারা v4.2.1312.1622 এর বিপরীতে নির্মিত যা প্রায় এক বছর আগে প্রকাশিত হয়েছিল । এই প্রতিশ্রুতিটি দেখুন যা মুক্তির কয়েক দিন আগে করা হয়েছিল। কেন এপিআই ডকুমেন্টগুলি আপডেট হয় না ...
স্টুয়ার্ট গ্র্যাসি

16

উপরে @ স্টার্ট গ্রাসির উত্তরটি সুপারিশ করুন।

var moqCredentialMananger = new Mock<ICredentialManager>();
moqCredentialMananger
                    .Setup(x => x.GetCredentialsAsync(It.IsAny<string>()))
                    .ReturnsAsync(new Credentials() { .. .. .. });

1

সঙ্গে Mock.Of<...>(...)জন্য asyncপদ্ধতি আপনি ব্যবহার করতে পারেন Task.FromResult(...):

var client = Mock.Of<IHttpClient>(c => 
    c.PostAsync(It.IsAny<Uri>(), It.IsAny<HttpContent>()) == Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))
);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.