简体   繁体   中英

Objective C - Unit Testing & Mocking Objects?

How do you unit test Objective C code? (iPhone)

In other languages such as java and .Net you can use Dependency Injection, to be able to unit test and pass mocked object in your current code. However, I could not find a reliable dependency injection framework for objective c.

Let's say you want to write a unit test for the code below, how can you mock MyObject?

- (void) methodToBeTested
{
     NSString str = @"myString";
     MyObject object = [[MyObject alloc] init];
     [object setString:str];
     [object doStuff];
     [object release];
}

This is how I would do it with dependency injection. Is there a similar way to achieve this on objective c?

@Inject MyObject object;

public void methodToBeTested()
{
     String str = "myString";
     // object is automatically instantiated (Dependency Injection)
     object.setString(str);
     object.doStuff();
}

Inversion of control is still feasible in objective-c. You can certainly design your classes with constructor-based or property-based dependency injection in mind but I don't think you'll find an annotation based dependency injection framework like you are used to.

[[ClassToBeTested alloc] initWithDependency:foo andOtherDepedency:bar];

ClassToBeTested *objectUnderTest = [[ClassToBeTested alloc] init];
objectUnderTest.dependency = foo;
objectUnderTest.otherDependency = bar;

I've seen a couple of different approaches to building dependency injection frameworks for objective-c including https://github.com/mivasi/Objective-IOC but I can't comment on their maturity or usefulness.

For object mocking and stubbing look at OCMock .

how can you mock MyObject?

- (void) methodToBeTestedWithObject:(MyObject *)object
{
     NSString str = @"myString";
     [object setString:str];
     [object doStuff];
}

To test:

- (void)testMethodToBeTested {
    id mockMyObject = [OCMock mockForClass:[MyObject class]];

    [[mockMyObject expect] setString:[OCMock any]];
    [[mockMyObject expect] doStuff];

    [objectToTest methodToBeTestedWithObject:mockMyObject];
    [mockMyObject verify];
}

Using, as mentioned in @Jonah's answer, the excellent OCMock . Don't bother trying to do capital-D, capital-I Dependency Injection in obj-c, it's more work than it's worth.

Here's a dependency injection framework for Objective-C: http://www.typhoonframework.org

Besides addressing on the design aspects of DI, it has a strong focus on being able to configure components for production vs test scenarios (integration testing). This includes:

  • Ability to inject values represented as strings - these are converted to the required type at runtime.
  • Configuration management via an external properties file.
  • Asynchronous test execution - allowing you to test methods that run on a background thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM