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 wr开发者_运维百科ite 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.
精彩评论