2012-08-22 16 views
25

में कनवर्ट करना मैं सिंक्रोनस एएसपीनेट कोड के शरीर को .NET 4.5 और नया async वाक्यविन्यास में परिवर्तित करने पर काम कर रहा हूं। अपने परीक्षण कोड के सभी फिर से लिखा जाना हैसिंक्रोनस Moq mocks को async

var retVal = new Foo(bar,baz); 
_myMock.Setup(x => x.DoSomething(123)).Returns(retVal); 

जब मैं async Task<Foo> DoSomething() को Foo DoSomething() से DoSomething के हस्ताक्षर कन्वर्ट,:

मैं ऐसा दिखता है जैसे परीक्षण कोड का एक बहुत कुछ है। मेरे वर्तमान वैकल्पिक हल की तरह कुछ करने के लिए मूल कोड में परिवर्तित करने के लिए है:

var retVal = new Foo(bar,baz); 
_myMock.Setup(x => x.DoSomething(123)) 
    .Returns(new Task<Foo>(()=>retVal)); 

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

मैंने उस फॉर्म में से कुछ करने के लिए रिटर्न्सएसिंक नामक एक विस्तार विधि बनाने का प्रयास किया, लेकिन मेरे पास कुछ प्रकार के अनुमानों के मुद्दे थे जो मैं काफी कम नहीं कर सका। क्या इस तरह के नकली को एसिंक विधि को बेहतर तरीके से संभालने के लिए एक मानक या आसान तरीका है?

उत्तर

20

Moq 4.2 एक ReturnsAsync() विस्तार विधि जोड़ा है, इसलिए यदि आप अब अपने खुद के जोड़ने की जरूरत है।

34

पहला, नामकरण: टास्क-आधारित असिंक्रोनस पैटर्न (टीएपी) का कहना है कि सभी विधियां जो असीमित हैं और Task एस को वापस Async के साथ समाप्त कर दिया जाना चाहिए। इसलिए, आपकी विधि का नाम DoSomethingAsync रखा जाना चाहिए।

दूसरा, Task का निर्माता Task बनाता है जो शुरू नहीं हुआ है, तो आपको इसे मैन्युअल रूप से Start() करना होगा। यदि आपका वास्तविक DoSomething विधि भी ऐसा करता है, तो वह फिर से टीएपी का पालन नहीं करता है और इसका मतलब है कि आपका कोड await के साथ अच्छी तरह से काम नहीं करेगा। इसके बजाय, आपको Task.Run(() => value), या इससे भी बेहतर, Task.FromResult(value) का उपयोग करना चाहिए।

तीसरा, यह बेहतर होगा अगर आपने हमें अपना कोड दिखाया जो अच्छी तरह से काम नहीं करता है, ताकि हम आपको बता सकें कि आपने गलती कहाँ की है।

अब, ReturnsAsync() विस्तार विधि का शरीर काफी सरल है, लेकिन मेरे लिए अधिकांश काम सही प्रकारों को ढूंढने में था (विशेष रूप से जब से मैं मोक नहीं जानता)। कोड इस तरह दिखता है:

public static class MoqExtensions 
{ 
    public static IReturnsResult<TMock> ReturnsAsync<TMock, TResult>(
     this IReturns<TMock, Task<TResult>> setup, TResult value) 
     where TMock : class 
    { 
     return setup.Returns(Task.FromResult(value)); 
    } 
}