本文介绍了如何使用未作为参数传递给方法的OCMock模拟对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一种方法想与OCMock一起测试,但不确定如何执行.我要嘲笑ExtClass未被定义为我的代码的一部分(外部库):

+(NSString *)foo:(NSString *)param
{
    ExtClass *ext = [[ExtClass alloc] initWithParam:param];
    if ([ext someMethod])
        return @"A";
    else
        return @"B";
}

提前谢谢!

解决方案

OCMock 2

id mock = [OCMockObject mockForClass:[ExtClass class]];
// We stub someMethod
BOOL returnedValue = YES;
[[[mock stub] andReturnValue:OCMOCK_VALUE(returnedValue)] someMethod];

// Here we stub the alloc class method **
[[[mock stub] andReturn:mock] alloc];
// And we stub initWithParam: passing the param we will pass to the method to test
NSString *param = @"someParam";
[[[mock stub] andReturn:mock] initWithParam:param];

// Here we call the method to test and we would do an assertion of its returned value...
[YourClassToTest foo:param];

OCMock3

// Parameter
NSURL *url = [NSURL URLWithString:@"http://testURL.com"];

// Set up the class to mock `alloc` and `init...`
id mockController = OCMClassMock([WebAuthViewController class]);
OCMStub([mockController alloc]).andReturn(mockController);
OCMStub([mockController initWithAuthenticationToken:OCMOCK_ANY authConfig:OCMOCK_ANY]).andReturn(mockController);

// Expect the method that needs to be called correctly
OCMExpect([mockController handleAuthResponseWithURL:url]);

// Call the method which does the work
[self.myClassInstance authStarted];

OCMVerifyAll(mockController);

注释

确保在两种情况下都存根两个方法(allocinit...方法).另外,请确保两个存根调用都是在类模拟的实例上进行的(而不是类本身).

文档: OCMock功能 类方法部分>

替代项

这个(奇怪的)解决方案可能在您要测试由于某种原因而无法重构的遗留代码的情况下很有用.但是,如果可以修改代码,则应该对其进行重构,并获得一个ExtClass对象作为参数而不是一个字符串,从而从该方法中委派了ExtClass的创建.您的生产和测试代码将更加简单明了,尤其是在更复杂的现实生活中,而不是在这个简单示例中.

I have a method I would like to test with OCMock but not sure how to do that. I need to mock ExtClass which isn't defined as part of my code (external library):

+(NSString *)foo:(NSString *)param
{
    ExtClass *ext = [[ExtClass alloc] initWithParam:param];
    if ([ext someMethod])
        return @"A";
    else
        return @"B";
}

Thanks in advance!

解决方案

OCMock 2

id mock = [OCMockObject mockForClass:[ExtClass class]];
// We stub someMethod
BOOL returnedValue = YES;
[[[mock stub] andReturnValue:OCMOCK_VALUE(returnedValue)] someMethod];

// Here we stub the alloc class method **
[[[mock stub] andReturn:mock] alloc];
// And we stub initWithParam: passing the param we will pass to the method to test
NSString *param = @"someParam";
[[[mock stub] andReturn:mock] initWithParam:param];

// Here we call the method to test and we would do an assertion of its returned value...
[YourClassToTest foo:param];

OCMock3

// Parameter
NSURL *url = [NSURL URLWithString:@"http://testURL.com"];

// Set up the class to mock `alloc` and `init...`
id mockController = OCMClassMock([WebAuthViewController class]);
OCMStub([mockController alloc]).andReturn(mockController);
OCMStub([mockController initWithAuthenticationToken:OCMOCK_ANY authConfig:OCMOCK_ANY]).andReturn(mockController);

// Expect the method that needs to be called correctly
OCMExpect([mockController handleAuthResponseWithURL:url]);

// Call the method which does the work
[self.myClassInstance authStarted];

OCMVerifyAll(mockController);

Notes

Ensure that in both cases you stub two methods (alloc and the init... method). Also, make sure that both stubbing calls are made on the instance of the class mock (not the class itself).

Docs: Class methods section in the OCMock features

Alternatives

This (strange)solution may be useful in case you want to test legacy code that due to whatever reason you cannot refactor. However, if you can modify the code you should refactor it and get an ExtClass object as a parameter, not a string, delegating the creation of ExtClass out of that method. Your production and test code would be simpler and clearer, specially in a more complex real life case, not in this simple example.

这篇关于如何使用未作为参数传递给方法的OCMock模拟对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 04:36