Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Practical examples of using stubs and mocks in unit tests

Practical examples of using stubs and mocks in unit tests

Mobile Optimized 2014

Victor Ilyukevich

June 29, 2014
Tweet

More Decks by Victor Ilyukevich

Other Decks in Programming

Transcript

  1. – Martin Fowler “There is a difference in that the

    stub uses state verification while the mock uses behavior verification.” http://martinfowler.com/articles/mocksArentStubs.html
  2. Stubs • Stubs drive the production code through different paths

    by returning predefined values in response to method calls from SUT (System Under Test). • You verify state of your SUT.
  3. enabledRemoteNotificationTypes it(@"is Allowed", ^{ id value = theValue(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound);

    ! UIApplication *app = [UIApplication sharedApplication]; [app stub:@selector(enabledRemoteNotificationTypes) andReturn:value]; ! [[theValue(manager.status) should] equal:theValue(CZAllowed)]; });
  4. Current date context(@"when current minute is 44", ^{ it(@"creates an

    event that starts on the next hour", ^{ NSDate *fakeNow = [NSDate dateFromYear:2012 month:1 day:14 hour:14 minute:44]; [NSDate stub:@selector(date) andReturn:fakeNow]; ! [event setupDefaultValues]; ! [[event.startsAt should] equal:[NSDate dateFromYear:2012 month:8 day:23 hour:15 minute:00]]; }); });
  5. NSCalendar context(@"when recurs on Sunday, Monday, Tuesday and Friday", ^{

    ! it(@"returns 'Sun, Mon, Tue, Fri'", ^{ [[reminder.displayShortRecurrenceDays should] equal:@"Sun, Mon, Tue, Fri"]; }); ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! }); });
  6. NSCalendar context(@"when recurs on Sunday, Monday, Tuesday and Friday", ^{

    context(@"in US", ^{ it(@"returns 'Sun, Mon, Tue, Fri'", ^{ [[reminder.displayShortRecurrenceDays should] equal:@"Sun, Mon, Tue, Fri"]; }); }); ! context(@"in Russia", ^{ beforeEach(^{ NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; calendar.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"ru_RU"]; calendar.firstWeekday = 2; ! [NSCalendar stub:@selector(currentCalendar) andReturn:calendar]; }); ! it(@"returns 'Пон, Вт, Пт, Вск'", ^{ [[reminder.displayShortRecurrenceDays should] equal:@"пн, вт, пт, вс"]; }); }); });
  7. Mocks • Behaviour verification, not state. • Mock know what

    should happen. • You verify that SUT behaves as expected, i.e. calls a method on a mock. • The tests ask the mock if everything went as expected.
  8. sharedInstance it(@"tracks 'Item viewed’ on appearing", ^{ KWMock *analytics =

    [KWMock nullMockForClass:[Analytics class]]; [Analytics stub:@selector(sharedInstance) andReturn:analytics]; ! [analytics should] receive:@selector(track:properties:) withArguments:@"Item viewed", @{ @"Type": @"Calendar event" }, nil]; ! TriggerViewAppearing(controller); });
  9. A crazy example of spying* it(@"shows alert 'Can't do this...'",

    ^{ KWMock *notInitializedAlert = [KWMock nullMockForClass:[UIAlertView class]]; KWCaptureSpy *spy = [notInitializedAlert captureArgument:@selector(initWithTitle: message: delegate: cancelButtonTitle: otherButtonTitles:) atIndex:1]; ! [UIAlertView stub:@selector(alloc) andReturn:notInitializedAlert]; ! [subject showUnableToShareAlertIfNeeded]; ! [[spy.argument should] equal:@"Can't do this right now..."]; });