سؤال

غالبا ما أجد في بلدي فون الهدف-C وحدة الاختبارات التي أريد كعب فئة الطريقة ، على سبيل المثالNSUrlConnection هو +sendSynchronousRequest:returningResponse:خطأ:الأسلوب.

المثال المبسط:

- (void)testClassMock
{
    id mock = [OCMockObject mockForClass:[NSURLConnection class]];
    [[[mock stub] andReturn:nil] sendSynchronousRequest:nil returningResponse:nil error:nil];
}

عند تشغيل هذا أحصل على:

Test Case '-[WorklistTest testClassMock]' started.
Unknown.m:0: error: -[WorklistTest testClassMock] : *** -[NSProxy doesNotRecognizeSelector:sendSynchronousRequest:returningResponse:error:] called!
Test Case '-[WorklistTest testClassMock]' failed (0.000 seconds).

لقد كان حقا صعوبة في العثور على أي وثائق على هذا, ولكن أفترض أن أساليب الفئة لا يدعمها OCMock.

لقد وجدت هذا غيض بعد الكثير من البحث في قوقل.يعمل لكن هو مرهقة جدا:http://thom.org.uk/2009/05/09/mocking-class-methods-in-objective-c/

هناك على أية حال أن تفعل هذا في OCMock?أو يمكن أن يفكر شخص ذكي OCMock فئة كائن التي يمكن أن تكون مكتوبة على إنجاز هذا النوع من الأشياء ؟

هل كانت مفيدة؟

المحلول

وقادمة من عالم روبي، وأنا أفهم بالضبط ما كنت تحاول إنجاز. على ما يبدو، كنت حرفيا ثلاث ساعات أمامي تحاول أن تفعل بالضبط نفس الشيء اليوم (بالتوقيت الشيء المنطقة: -؟).

وعلى أي حال، أنا <م> نعتقد أن هذا غير معتمد في اتجاه واحد سوف ترغب في OCMock بسبب الإستئصال طريقة الطبقة يحتاج للوصول حرفيا إلى الطبقة وتغيير تنفيذ منهجه بغض النظر عن متى وأين، أو الذي يستدعي الأسلوب. هذا على عكس ما يبدو OCMock أن تفعل وهي لتوفر لك الكائن الوكيل الذي تلاعب وتعمل على خلاف ذلك مباشرة وبدلا من كائن "الحقيقي" من الفئة المحددة.

وعلى سبيل المثال، فإنه يبدو من المعقول أن ترغب في كعب NSURLConnection + sendSynchronousRequest: returningResponse: خطأ: الأسلوب. ومع ذلك، فمن المعتاد أن استخدام هذه الدعوة ضمن التعليمات البرمجية لدينا ودفن إلى حد ما، مما يجعل من حرج جدا لأنه بالحدود وتبادل في كائن وهمي للطبقة NSURLConnection.

لهذا السبب، أعتقد أن نهج "طريقة swizzling" كنت قد اكتشفت، في حين لا مثير، هو بالضبط ما تريد القيام به لالإستئصال أساليب الفئة. القول انها <م> جدا مرهقة يبدو المدقع - ماذا عن نتفق انها "ائقة" وربما يست مريحة كما OCMock يجعل الحياة بالنسبة لنا. ومع ذلك، انها حل موجزة جدا لهذه المشكلة.

نصائح أخرى

تحديث OCMock 3

OCMock حدثت الجملة من أجل دعم أسلوب فئة الإستئصال:

id classMock = OCMClassMock([SomeClass class]);
OCMStub(ClassMethod([classMock aMethod])).andReturn(aValue);

التحديث

OCMock الآن يدعم أسلوب فئة الإستئصال في الخروج من مربع.العملية البرمجية يجب أن تعمل الآن كما نشر.إذا كان هناك أسلوب مثيل مع نفس اسم الصف طريقة بناء الجملة هو:

[[[[mock stub] classMethod] andReturn:aValue] aMethod]

انظر OCMock ميزات.

الرد الأصلي

نموذج التعليمات البرمجية التالي باري ارك الجواب.

وهمية الدرجة فقط الإستئصال connectionWithRequest:مندوب:

@interface FakeNSURLConnection : NSURLConnection
+ (id)sharedInstance;
+ (void)setSharedInstance:(id)sharedInstance;
+ (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id<NSURLConnectionDelegate>)delegate;
- (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id<NSURLConnectionDelegate>)delegate;
@end
@implementation FakeNSURLConnection
static id _sharedInstance;
+ (id)sharedInstance { if (!_sharedInstance) { _sharedInstance = [self init]; } return _sharedInstance; }
+ (void)setSharedInstance:(id)sharedInstance { _sharedInstance = sharedInstance; }
+ (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id<NSURLConnectionDelegate>)delegate {
    return [FakeNSURLConnection.sharedInstance connectionWithRequest:request delegate:delegate];
}
- (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id<NSURLConnectionDelegate>)delegate { return nil; }
@end

التحول من السخرية:

{
    ...
    // Create the mock and swap it in
    id nsurlConnectionMock = [OCMockObject niceMockForClass:FakeNSURLConnection.class];
    [FakeNSURLConnection setSharedInstance:nsurlConnectionMock];
    Method urlOriginalMethod = class_getClassMethod(NSURLConnection.class, @selector(connectionWithRequest:delegate:));
    Method urlNewMethod = class_getClassMethod(FakeNSURLConnection.class, @selector(connectionWithRequest:delegate:));
    method_exchangeImplementations(urlOriginalMethod, urlNewMethod);

    [[nsurlConnectionMock expect] connectionWithRequest:OCMOCK_ANY delegate:OCMOCK_ANY];

    ...
    // Make the call which will do the connectionWithRequest:delegate call
    ...

    // Verify
    [nsurlConnectionMock verify];

    // Unmock
    method_exchangeImplementations(urlNewMethod, urlOriginalMethod);
}

وهنا هو 'جوهر' لطيفة مع تنفيذ أفرط لأساليب الفئة: https://gist.github.com / 314009

إذا قمت بتعديل أسلوب بك تحت الاختبار لاتخاذ المعلمة التي تضخ هذه الطبقة من NSURLConnection، ثم أنه من السهل نسبيا أن يمر في همية يستجيب لمحدد معين (قد يكون لديك لإنشاء فئة وهمية في وحدة الاختبار الذي لديه محدد كطريقة سبيل المثال وهمية تلك الفئة). من دون هذه الحقن، وكنت تستخدم أسلوب فئة، أساسا باستخدام NSURLConnection (الطبقة)، وعن المفردة وبالتالي وقعوا في نموذج مضاد لاستخدام كائنات المفرد وقابلية الاختبار من التعليمات البرمجية الخاصة بك قد لحقت بهم.

وصلة إلى مشاركة المدونة في السؤال وRefuX جوهر أوحت لي من أجل التوصل إلى كتلة تمكين تنفيذ أفكارهم: الشبكي : //gist.github.com/1038034

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top