网络编程

OCMock 3 参考

来源:http://www.xtcsyb.com 作者:永利402游戏网站-永利402com官方网站 时间:2019-09-14 02:18

Mock介绍

什么是mock测试?

对于一些不容易构造或不容易获取的对象,此时你可以创建一个虚拟的对象(mock object)来完成测试。

例如你可能要尝试100次才会返回一个NSError,通过mock object你可以自行创建一个NSError对象,测试在出错情况下程序的处理是否符合你的预期。

例如你要连接服务器但是服务器在实验室,你在外工作的时候就无法测试了(小弟就试过这种情况,非常反感),这个时候你可以创建一个虚拟的服务器,并返回一些你指定的数据,从而绕过服务器。

例如假设你要访问一个数据库,但是访问过程的开销巨大,这时你可以虚拟一个数据库,并且返回一些自行定制的数据,从而绕过了数据库的访问。

mock的思想很简单:没有条件?我们就自行创造条件。

1.Creating mock objects

OCMock介绍

OCMock是一个用于为iOS或Mac OS X项目配置Mock测试的开源项目。

其实现思想就是根据要mock的对象的class来创建一个对应的对象,并且设置好该对象的属性和调用预定方法后的动作(例如返回一个值,调用代码块,发送消息等等),然后将其记录到一个数组中,接下来开发者主动调用该方法,最后做一个verify,从而判断该方法是否被调用,或者调用过程中是否抛出异常等。

其实就是可以把它当做我们伪造的一个对象,我们给它一些预设的值之类的,然后就可以进行对应的验证了。

1.1Class mocks


idclassMock=OCMClassMock([SomeClassclass]);


配置

到OCMock的官网下载dmg文件,打开后里面有个iOS library文件夹。把iOS library里的文件加入到你的项目里,按这篇教程来进行配置。

OCMock文档,可以到这里查看如何详细使用OCMock。

1.2Protocol mocks


idprotocolMock=OCMProtocolMock(@protocol(SomeProtocol));


Creates a mock object that can be used as if it were an instance of an object that implementsSomeProtocol. Otherwise they work like class mocks.

创建一个mock对象,如果它是一个实例对像实现的SomeProtocol能使用他,否侧这个工作像classmock

例子中使用到的方法说明

(以下数字为OCMock文档中的数字目录)

1.1. Class mocks

id classMock = OCMClassMock([SomeClass class]);

创建mock object当做类的实例。

2.1. Stubbing methods that return objects

OCMStub([mock someMethod]).andReturn;

告诉mock object当它调用someMethod的时候应该返回anObject。

3.1. Verify-after-running

id mock = OCMClassMock([SomeClass class]);/* run code under test */OCMVerify([mock someMethod]);

/* run code under test */写一些对应的代码,然后 OCMVerify([mock someMethod]);验证方法是否被调用。

3.2. Stubs and verification

id mock = OCMClassMock([SomeClass class]);OCMStub([mock someMethod]).andReturn;/* run code under test */OCMVerify([mock someMethod]);

4.1. The any constraint

OCMStub([mock someMethodWithAnArgument:[OCMArg any]])OCMStub([mock someMethodWithPointerArgument:[OCMArg anyPointer]])OCMStub([mock someMethodWithSelectorArgument:[OCMArg anySelector]])

1.3Strict class and protocol mocks


idclassMock=OCMStrictClassMock([SomeClassclass]);

idprotocolMock=OCMStrictProtocolMock(@protocol(SomeProtocol));


创建一个严格的mock对象模式。默认情况下mock很好,他们返回nil(或正确的返回类型默认值)的方法被调用。相比之下,严格Mock引发一个异常当他们收到的方法没有明确的预期。请参阅下面的严格模拟和期望。

实际例子

以下的例子Demo:DSOCMockDemo

使用了文档中的OCMock文档中以下几种方法:1.1 Class mocks2.1 Stubbing methods that return objects3.1 Verify-after-running3.2 Stubs and verification4.1 The any constraint

这是一个来自于OCMock上的例子。我这里就做一下翻译和Demo。

为了使我们更加具体的理解使用OCMock,这里假设我们写了一个接收来自于Twitter信息的应用。

有一个TwitterViewController类,一个TwitterConnection用来调用Twitter API得到数据,和一个TweetView类用来显示tweet对象。

下面是TwitterViewController类,有connectiontweetView对象。

@interface TwitterViewController : UIViewController@property(nonatomic, strong)TwitterConnection *connection;@property(nonatomic, strong)TweetView *tweetView;- updateTweetView;@end

TwitterConnection是一个网络连接类,有一个fetchTweets方法用来接收请求回来的信息。返回一个Tweet对象的数组。

@interface TwitterConnection : NSObject- (NSArray *)fetchTweets;@end

TweetView有一个addTweet:方法用来添加每一个Tweet对象到页面上。

@interface TweetView : UIView- addTweet:aTweet;@end

为什么使用mocks用来测试

当我们为updateTweetView来写一个测试类的时候我们要考虑它有哪些相对应的依赖,也就是TwitterConnection和TweetView。在这个例子里我们需要实例化一个真正的TwitterConnection对象来请求真实数据然后使用它。这样的话会有几个问题:

  • 使用真实的connection会使测试变慢,因为它还要去请求网络。
  • 我们永远不知道每一次Twitter返回的数据是什么。
  • 很难测试错误的返回,因为Twitter一般不会返回错误。

解决的方法就是伪造一个假的connection,既一个stub。

下图就是使用测试的代码:

图片 1

OCMock会在mock实例上没有找到相同名字的实例方法的时候去找同名的类方法。

使用例子一种的类,给TwitterConnection加个类方法+ (NSArray *)fetchTweets2;

我们可以看到例子2和例子中classMethod和instanceMethod的stub方式一样。

使用了文档中的OCMock文档中以下几种方法:1.3 Strict class and protocol mocks7.1 Expect-run-verify7.2 Strict mocks and failing fast7.3 Stub actions and expect

当我们使用普通的mock的时候是这样的:

- testStrictMock3{ id classMock = OCMClassMock([TweetView class]); //设置期望或预设,这个classMock需要执行addTweet方法且参数不为nil。 不然的话会抛出异常 //OCMExpect([classMock addTweet:[OCMArg isNotNil]]); //OCMStub([classMock addTweet:[OCMArg isNotNil]]); /* 如果不执行以下代码的话会抛出异常 */ Tweet *testTweet = [[Tweet alloc] init]; testTweet.userName = @"齐滇大圣"; [classMock addTweet:testTweet]; OCMVerifyAll(classMock);}

这表示一种友好的mock,不会在没有OCMExpect或OCMStub设置类的所有方法时抛出异常。以上代码把OCMExpect和OCMStub注释掉时不会报错。

还有一种表示严格的mock:OCMStrictClassMock,如果把OCMExpect和OCMStub注释掉时会报错,它要求你执行类中的所有方法,所以比较适合用来测试必须实现的方法,代码如下:

- testStrictMock3{ id classMock = OCMStrictClassMock([TweetView class]); //OCMExpect([classMock addTweet:[OCMArg isNotNil]]); //OCMStub([classMock addTweet:[OCMArg isNotNil]]); Tweet *testTweet = [[Tweet alloc] init]; testTweet.userName = @"齐滇大圣"; [classMock addTweet:testTweet]; OCMVerifyAll(classMock);}

1.4 Partial mocks(部分 mocks)

idpartialMock=OCMPartialMock(anObject);

Creates a mock object that can be used in the same way asanObject. Any method that is not stubbed is forwarded toanObject. When a method is stubbed and that method is invoked using a reference to the real object, the mock will still be able to handle the invocation. Similarly, when a method is invoked using a reference toanObject, rather than the mock, it can still be verified later.

译:创建一个mock对象,可用于asanObject一样。不是的是转发toanObject的任何方法。当一个方法的调用,方法使用对真实对象的引用,mock仍然能够处理调用。同样,当调用一个方法使用toanObject的引用,而不是mock,它仍然可以得到证实。

There are some subtleties when using partial mocks. Seepartial mocksbelow.

参考

ocmock源码[iOS单元测试系列]单元测试编码规范[iOS单元测试系列]-译-OCMock常见使用方式Introduction to mocking with OCMock

1.5 Observer mocks(观察 mocks)

idobserverMock=OCMObserverMock();

Creates a mock object that can be used to observe notifications. The mock must be registered in order to receive notifications. Seeobserver mocksbelow for details.

译:创建一个mock对象,可以用来观察通知。mock必须注册以接收通知。Seeobserver mocksbelow详情。

2 Stubbing methods(stub方法)

2.1 Stubbing methods that return objects(stub方法返回对象)

OCMStub([mocksomeMethod]).andReturn(anObject);

Tells the mock object that whensomeMethodis called it should returnanObject.

译:讲述了mock对象,当someMethod 呼叫它应该返回一个对象。

2.2 Stubbing methods that return values(stub返回值的方法)

OCMStub([mockaMethodReturningABoolean]).andReturn(YES);

For methods that return primitive values it is important to use the right type of value. If, for example, a method returns alongbut the stub uses anintan error will occur. The message will include the expected and the actual type (using Objective-C type codes such as “q” forlongand “i” forint).

译:返回原始值的方法是很重要的使用正确的类型的值。例如,如果一个方法返回alongbut stub使用anintan就会发生错误。消息将包括预期的和实际的类型(使用objective

  • c类型代码如“q”forlongand“我”)。

2.3 Delegating to another method(委托给另一个方法)

OCMStub([mocksomeMethod]).andCall(anotherObject,@selector(aDifferentMethod));

In this case the mock object will callaDifferentMethodonanotherObjectwhensomeMethodis called. The signature of the replacement method must be the same as that of the method that is replaced. Arguments will be passed, and the return value of the replacement method is returned from the stubbed method. It is common to implement the replacement method in the test case itself.

译:在这种情况下,将callaDifferentMethodonanotherObjectwhensomeMethodis调用mock对象。替代方法的签名必须与被替换的方法。参数将传递和返回值返回的替代方法的方法。通常实现替代方法在测试用例本身。

2.4 Delegating to a block(委托给 块)

OCMStub([mocksomeMethod]).andDo(^(NSInvocation*invocation){/* block that handles the method invocation */});

The mock object will call the passed block whensomeMethodis called. The block can read the arguments from the invocation object, and it can use the invocation object to set up a possible return value.

译:mock对象将调用通过阻止someMethodis打电话时。块可以读取的参数调用对象,它可以使用调用对象建立一个可能的返回值

2.5 Returning values in pass-by-reference arguments(返回值引用传递参数)

OCMStub([mocksomeMethodWithReferenceArgument:[OCMArgsetTo:anObject]]);

OCMStub([mocksomeMethodWithReferenceArgument:[OCMArgsetToValue:OCMOCK_VALUE((int){aValue})]]);

The mock object will set the reference that is passed to the method toanObjectandaValue. UsesetTo:for pass-by-reference arguments that return objects andsetToValue:andOCMOCK_VALUE()for arguments that return primitives.

译:mock对象将toanObjectandaValue的引用传递给方法。UsesetTo:andsetToValue引用传递参数,返回对象:andOCMOCK_VALUE()的参数返回原语。

2.6 Invoking block arguments(调用块参数)

OCMStub([mocksomeMethodWithBlock:[OCMArginvokeBlock]]);

OCMStub([mocksomeMethodWithBlock:([OCMArginvokeBlockWithArgs:@"First arg",nil])]);

The mock object will invoke the block passed as an argument to the stubbed method. If the block takes arguments andinvokeBlockis used, the default values for the argument types are used, e.g. zero for a numerical type. UsinginvokeBlockWithArgs:it is possible to specify which arguments to invoke the block with; non-object arguments must be wrapped in value objects and the expression must be wrapped in round brackets.

译:mock对象将调用块作为参数传递的方法。andinvokeBlockis如果块参数使用默认值的参数类型,如零数值类型。UsinginvokeBlockWithArgs:可以指定哪个参数来调用块;非参数必须用值对象和表达式必须用圆括号。

2.7 Throwing exceptions(抛出异常)

OCMStub([mocksomeMethod]).andThrow(anException);

WhensomeMethodis invoked the stub will throwanException.

译:当someMethodis调用stub将throwanException。

2.8 Posting notifications(发布通知)

OCMStub([mocksomeMethod]).andPost(aNotification);

When someMethodis invoked the stub will postaNotification.

译:当someMethodis调用stub将发布通知。

2.9 Chaining stub actions(链接stub的行为)

OCMStub([mocksomeMethod]).andPost(aNotification).andReturn(aValue);

All actions such asandReturnandandPostcan be chained. In this example the mock object will post a notification and return the value.

译:所有操作这样的asandReturnandandPostcan是链接。在这个例子中mock对象将发布一个通知和返回的值。

2.10 Forwarding to the real object / class(转发到真正的对象/类)

OCMStub([mocksomeMethod]).andForwardToRealObject();

When using a partial mock and when mocking class methods it is possible to stub a method and forward it to the real object (in case of partial mocks) or to the class (when mocking class methods). This is only useful when chaining actions or when usingexpectations.

2.11 Doing nothing

 OCMStub([mocksomeMethod]).andDo(nil);

It is possible to passnilinstead of a block toandDo. This is only useful with partial mocks or when mocking class methods. In these cases usingandDo(nil)effectively suppresses the behaviour in the existing class.

译:当使用部分mock当mock类方法可以存根方法并将其转发给实际对象(在部分mock的情况下)或类(当mock类方法)。这只是有用或者当usingexpectations链接操作

3 Verifying interactions(验证相互作用)

3.1 Verify-after-running(验证-前-运行)

idmock=OCMClassMock([SomeClassclass]);/* run code under test */OCMVerify([mocksomeMethod]);

Verifies thatsomeMethodhas been called by the code under test. If the method has not been invoked an error is reported. In Xcode and AppCode the error is reported on the line of the verify, for other test environments an exception is thrown.

译:验证thatsomeMethodhas被测试的代码。如果没有被调用的方法一个错误报告。在Xcode和本地错误报告的验证,为其他测试环境就会抛出一个异常。

It is possible to useargument constraintsin the verify statement.

3.2 Stubs and verification(stub和验证)

idmock=OCMClassMock([SomeClassclass]);

OCMStub([mocksomeMethod]).andReturn(myValue);

/* run code under test */

OCMVerify([mocksomeMethod]);

It is possible to stub a method and still verify that it has been called.

译:它仍然被称为存根方法和验证

4 Argument constraints(参数约束)

4.1 The any constraint(任何约束)

OCMStub([mocksomeMethodWithAnArgument:[OCMArgany]])OCMStub([mocksomeMethodWithPointerArgument:[OCMArganyPointer]])OCMStub([mocksomeMethodWithSelectorArgument:[OCMArganySelector]])

Adds a stub for the methods which is active for all invocations, no matter what argument is passed. Pointers and selectors require special treatment as shown above. Arguments that are neither objects nor pointers or selectors cannot be ignored using ananyplaceholder (for details see thisforum thread). See just below for a workaround.

4.2 Ignoring non-object arguments(忽略非参数)

[[[mockstub]ignoringNonObjectArgs]someMethodWithIntArgument:0]

This tells the mock to ignore all non-object arguments in the invocation. It will accept any invocation ofsomeMethodWithIntArgument:no matter what argument is actually passed. If the method has object arguments as well as non-object arguments, the object arguments can still be constrained as usual using the methods onOCMArg.

译:这告诉mock忽略所有非参数的调用。它将接受任何调用someMethodWithIntArgument:无论什么观点实际上是通过。如果参数和非参数方法对象,对象参数仍然可以限制像往常一样OCMArg上使用的方法

NOTE:this should have a modern syntax.

4.3 Matching arguments(匹配的参数)

OCMStub([mocksomeMethod:aValue)OCMStub([mocksomeMethod:[OCMArgisNil]])OCMStub([mocksomeMethod:[OCMArgisNotNil]])OCMStub([mocksomeMethod:[OCMArgisNotEqual:aValue]])OCMStub([mocksomeMethod:[OCMArgisKindOfClass:[SomeClassclass]]])OCMStub([mocksomeMethod:[OCMArgcheckWithSelector:aSelectoronObject:anObject]])OCMStub([mocksomeMethod:[OCMArgcheckWithBlock:^BOOL(idvalue){/* return YES if value is ok */}]])

If an argument is passed when the stub is created, the stub only matches invocations with that exact argument. Calls with different arguments are not matched. TheOCMArgclass provides several methods that allow matching values in different ways.

译:如果一个参数是通过创建存根时,存根只匹配调用以同样的论点。调用不同的参数不匹配。OCMArg类提供了一些方法,允许以不同的方式匹配的值

ForcheckWithSelector:onObject:, when the mock object receivessomeMethod:, it invokesaSelectoronanObject. If the method takes an argument the mock will pass the argument that was passed tosomeMethod:. The method should return a boolean indicating whether the argument matched the expectation or not.

译:checkWithSelector:onObject:,当模拟对象接收到someMethod:,它调用aSelector anObject。如果方法接受一个参数的模拟将参数传递给someMethod:。方法应该返回一个布尔值表示是否参数匹配的期望。

4.4 Using Hamcrest matchers(使用Hamcrest匹配器)

OCMStub([mocksomeMethod:startsWith(@"foo")])

It is also possible to useHamcrest matchers. This will only work when the Hamcrest framework is explicitly linked by the unit test bundle. OCMock does not declare a dependency on Hamcrest and discovers it using runtime functions.

译:还可以使用Hamcrest匹配器。这只会工作Hamcrest框架明确相关的单元测试包。OCMock不声明一个依赖Hamcrest和发现它使用运行时功能。

5Mocking class methods

5.1 Stubbing class methods(stub类方法)

idclassMock=OCMClassMock([SomeClassclass]);

OCMStub([classMockaClassMethod]).andReturn(@"Test string");

// result is @"Test string"

NSString*result=[SomeClassaClassMethod];

Stubs for class methods are set up exactly like stubs for instance methods. However, behind the scenes the mock object makes some changes to the class. (It dynamically creates a new meta class and makes the class use that instead of its own meta class.) This allows OCMock to stub calls which are made directly to the class.

译:存根类方法建立的存根实例方法完全一样。然而,在幕后模拟对象使得类的一些变化。(它动态地创建一个新的元类,使类使用,而不是自己的元类)。这允许OCMock存根调用直接到类。

IMPORTANT:If the mock object that added a stubbed class method is not deallocated then the stubbed method will persist across tests. If multiple mock objects manipulate the same class at the same time the behaviour is undefined.

译:重要:如果模拟对象添加了一个sub类方法不一致的方法,测试会持续。如果多个模拟对象同时操作同一个类的行为是未定义的

5.2 Verifying invocations of class methods(验证类方法的调用)

idclassMock=OCMClassMock([SomeClassclass]);

/* run code under test */

OCMVerify([classMocka ClassMethod]);

Verification is done in the same way as with instance methods. As described above, calls can be made directly to the class.

译:实例验证后以同样的方式与方法。如上所述,可以直接调用类。

5.3 Disambiguating class and instance methods(二义性消除类和实例方法)

idclassMock=OCMClassMock([SomeClassclass]);

OCMStub(ClassMethod([classMockambiguousMethod])).andReturn(@"Test string");

// result is @"Test string"

NSString*result=[SomeClassam biguousMethod];

In cases where a class method should be stubbed but the class also has an instance method with the same name as the class method, as assumed withambiguousMethodabove, the intent to mock the class method must be made explicit usingClassMethod().

译:在这种情况下,一个sub类方法,但具有相同名称的类也有一个实例方法的类方法,假定withambiguousMethodabove,意图模拟类方法必须明确usingClassMethod()。

5.4 Restoring the class(恢复类)

idclassMock=OCMClassMock([SomeClassclass]);

/* do stuff */

[classMock stopMocking];

The class can be returned to its original state by callingstopMocking. This is only necessary if the original state must be restored before the end of the test. The  mock automatically callsstopMockingduring its own deallocation.

译:他类可以通过调用stopMocking回到初始状态。这仅仅是必要的,如果必须在恢复前结束测试。mocK自动调用stopMocking期间自己的回收。

When the class is returned to its original state, its meta class will be switched back to the original meta class. This effectively removes all the stubs. However, this also makes it impossible for the mock to add new stubs or to verify interactions. You should really not use a mock after having calledstopMocking.

译:当这个类回到原来的状态,它的元类将切换回原来的元类。这将有效消除所有的subs。然而,这也使得模拟无法添加新存根或验证交互。你不应该使用一个模拟称为stopMocking后

6 Partial mocks(部分 mocks)

6.1 Stubbing methods(sub方法)

idpartialMock=OCMPartialMock(anObject);

OCMStub([partialMocksomeMethod]).andReturn(@"Test string");

// result1 is @"Test string"

NSString*result1=[partialMocksomeMethod];

// result2 is @"Test string", too!

NSString*result2=[anObjectsomeMethod];

From an API perspective stubs on partial mocks are set up in the same way as on class and protocol mocks. Partial mocks alter the class of the mocked object, though. (In fact, they create a subclass and switch the class of the mocked object to that subclass.) This means that calls using a reference to the real object, even includingselfin methods where the object calls itself, are also affected by stubs and expectations.

译:从一个API的角度来看subs上部分mock设置相同的方式mock类和协议。部分mock改变类 的对象,。(事实上,他们创建一个子类和开关类子类的对象。)这意味着调用使用对真实对象的引用,甚至包括自我在对象调用方法本身,也受到stubs和期望。

6.2 Verifying invocations(验证调用)

idpartialMock=OCMPartialMock(anObject);

/* run code under test */

OCMVerify([partialMocksomeMethod]);

Verification is done in the same way as with class and protocol mocks. As described just above, calls using a reference to the real object are intercepted, too. There is no need to insure that a reference to the mock is used, calls can be made using references to the real object.

译:验证后以同样的方式与mock类和协议。上方,所述调用使用拦截,对真实对象的引用。不需要确保使用mock的引用,称可以通过对真实对象的引用。

6.3 Restoring the object(恢复的对象)

idpartialMock=OCMPartialMock(anObject);

/* do stuff */

[partialMock stopMocking];

The real object can be returned to its original state by callingstopMocking. This is only necessary if the original state must be restored before the end of the test. The partial mock automatically callsstopMockingduring its own deallocation.

译:真正的对象可以通过调用stopMocking回到初始状态。这仅仅是必要的,如果必须在结束前恢复原始状态测试。部分mock自动调用stopMocking期间自己的回收。

When the object is returned to its original state, its class will be switched back to the original class. This effectively removes all the stubs. However, this also makes it impossible for the partial mock to add new stubs or to verify interactions. You should really not use a partial mock after having calledstopMocking.

译:当对象返回到原来的状态,它的类将切换回原始类。这将有效消除所有的存根。然而,这也使得部分模拟无法添加新存根或验证交互。你应该不使用部分模拟称为stopMocking后。

7 Strict mocks and expectations(严格的Mock和期望)

7.1 Expect-run-verify(期望-运行-验证)

idclassMock=OCMClassMock([SomeClassclass]);

OCMExpect([classMocksomeMethodWithArgument:[OCMArgisNotNil]]);

/* run code under test, which is assumed to call someMethod */

OCMVerifyAll(classMock)

This is the original approach to mocking. First the mock object is set up with expectations, then the code under test is run, and afterwards the expectations are verified. If an expected method has not been invoked, or has not been invoked with the right arguments, then an error is reported. As shown it is possible to useargument constraintsin the expect statement. Strict mocks can be created for classes and protocols.

译:这是原始的mock方法。第一次模拟对象设置期望,然后运行测试代码,验证之后的期望。如果预期的方法没有被调用,或者没有正确的调用参数,然后会报告一个错误。如图所示是可能期望语句中使用参数约束。严格的mock可以创建类和协议。

If in doubt use the newerverify-after-runningapproach described inVerifying interactions.

译:如果在怀疑使用较新的verify-after-running方法验证中所描述的交互

7.2 Strict mocks and failing fast(严格mock 与 快速失败)

idclassMock=OCMStrictClassMock([SomeClassclass]);

[classMock someMethod];

//thiswillthrowanexception

The mock has been set up as a strict mock without any expectations. CallingsomeMethodwill cause the mock to throw an exception. This is also known asfailing fastbecause the test fails immediatly when the unexpected call is made. Only strict mocks fail fast.

译:mock被设置为一个严格模拟没有任何期望。调用someMethod将导致mock抛出异常。这也被称为快速地失败,因为测试失败马上当意想不到的调用。只有严格的mock快速失败

7.3 Stub actions and expect(stub 行为 与期望)

idclassMock=OCMStrictClassMock([SomeClassclass]);

OCMExpect([classMocksomeMethod]).andReturn(@"a string for testing");

/* run code under test, which is assumed to call someMethod */

OCMVerifyAll(classMock)

It is possible to useandReturn,andThrow, etc with expectations, too. This will then run the stub action if and when the method is invoked and, on verify, ensure that the method was actually invoked.

译:可以使用andReturn、规划等与预期。然后运行stub行动如果和调用方法时,在验证,确保实际上是调用的方法。

7.4 Verify with delay(验证与延迟)

idmock=OCMStrictClassMock([SomeClassclass]);

OCMExpect([mocksomeMethod]);

/* run code under test, which is assumed to call someMethod eventually */

OCMVerifyAllWithDelay(mock,aDelay);

In certain cases the expected method will only be called when the run loop is active. For these cases it is possible to delay the verification for a while. Note thataDelay(expressed asNSTimeInterval) is the maximum the mock will wait. It normally returns as soon as the expectations have been met.

译:在某些情况下预期的方法只会调用运行循环时活跃。在这些情况下,有可能延迟验证一段时间。注意,aDelay(表示为NSTimeInterval)是最大的模拟等。它通常返回一旦已达到预期。

7.5 Verifying in order

idmock=OCMStrictClassMock([SomeClassclass]);

[mocksetExpectationOrderMatters:YES];

OCMExpect([mocksomeMethod]);

OCMExpect([mockanotherMethod]);

// calling anotherMethod before someMethod will cause an exception to be thrown  之前调用anotherMethod someMethod会导致抛出一个异常

[mockanotherMethod];

The mock can be told to verify that expected methods are called in the same order as the expectations are set up. As soon as a method is called that is not next on the “expected list” the mock will fail fast and throw an exception.

译:模拟可以告诉确认预计方法的预期设置的顺序相同。当一个方法被调用,不是下一个“期望列表”模拟将快速失败,抛出一个异常。

8 Observer mocks

8.1 Setup

idobserverMock=OCMObserverMock();

[notificatonCenteraddMockObserver:aMockname:SomeNotificationobject:nil];

[[mockexpect]notificationWithName:SomeNotificationobject:[OCMArgany]];

Creates a mock object that can be used to observe notifications, registers it with a notification center, and tells the mock to expectSomeNotificationwith any object.

译:创建一个模拟对象,可以用来观察通知,注册通知中心,并告诉模拟期望SomeNotification与任何对象。

8.2 Verification

OCMVerifyAll(observerMock);

Currently observer mocks are always strict, they will raise an exception when an unexpected notification is received. This implies that individual notifications cannot be verified after the fact. All notifications must be set up with expect, and they are verified together after the code under test has run usingOCMVerifyAll.

译:目前观察者mock总是严格,他们将意外收到通知时引发异常。这意味着个人通知不能验证后的事实。所有的通知都必须设置期望,他们一起验证代码在测试后usingOCMVerifyAll运行。

9 Advanced topics(高级主题)

9.1 Failing fast for regular (nice) mocks(没有快速的定期(nice)模拟)

On a strict mock object, when a method is called that has not been mocked (using some variant of stub or expect) the mock object will raise an exception. It willfail fast. Regular mock objects simply return the default value for the return type. Regular mocks can be configured on a per-method basis to fail fast:

译:严格的mock对象,当一个方法被调用,没有mock(使用stub或期望的一些变体)mock对象将引发一个异常。它会很快失败。常规mock对象仅仅返回返回类型的默认值。常规模拟可以配置在每个方法的基础上快速失败:

idmock=OCMClassMock([SomeClassclass]);

OCMReject([mocksomeMethod]);

In this case the mock will accept all methods exceptsomeMethod; if that is invoked the mock will throw an exception.

译:在这种情况下,mock将接受所有方法exceptsomeMethod;如果这是调用模拟将抛出一个异常。

9.2 Re-throwing fail fast exceptions in verify all(验证所有抛出收到快速失败异常)

In fail-fast mode an exception might not cause the test to fail. This can happen when the call stack for the method does not end in the test. Fail fast exceptions will be re-thrown whenOCMVerifyAllis called. This makes it possible to ensure that unwanted invocations from notifications etc. can be detected.

译:在快速失败模式异常可能不会导致测试失败。这可能发生在调用堆栈的方法并不在测试结束。快速失败异常将re-thrown whenOCMVerifyAllis调用。这可以确保不必要的调用从通知等可以被检测出来。

9.3 Stubbing methods that create objects(stub创建对象的方法)

idclassMock=OCMClassMock([SomeClassclass]);

OCMStub([classMockcopy])).andReturn(myObject);

It is possible to stub class and instance methods that conceptually create objects. OCMock automatically adjusts the reference count of the returned object when stubbing methods that have a name that begins withalloc,new,copy, ormutableCopy.

译:是可能的stub类和实例概念上创建对象的方法。OCMock自动调整stub方法时返回的对象的引用计数的名称始于alloc,新的副本,或者mutableCopy

idclassMock=OCMClassMock([SomeClassclass]);

OCMStub([classMocknew])).andReturn(myObject);

It possible, although not advisable, to stub outnewfor a class. If you find yourself doing this a lot, please consider thedependency injectionpattern.

译:成为可能,尽管不明智,存根outnewfor类。如果你发现自己这样做,请考虑thedependency injectionpattern。

IMPORTANT:It is not possible to stub theinitmethod, because that is implemented by the mock itself.

译:重要:sub init方法是不可能的,因为这是由mock实现本身。

9.4 Instance-based method swizzling(基本于实例方法 swizzling)

In a nutshell,Method Swizzlingdescribes the replacement of a method implementation with a different implementation at runtime. Using partial mocks and theandCallaction OCMock allows such replacements on a per-instance basis.

译:简而言之,swizzling描述方法的替代方法在运行时实现使用不同的实现。完好无损地行动OCMock允许使用部分mock和替换每个实例基础。

idpartialMock=OCMPartialMock(anObject);

OCMStub([partialMocksomeMethod]).andCall(differentObject,@selector(differentMethod));

After these two lines, whensomeMethodis sent toanObjectthe implementation of that method is not invoked. Instead,differentMethodis called ondifferentObject. Other instances of the same class are not affected; for these the original implementation ofsomeMethodis still invoked. The methods can have different names but their signatures should be the same.

译:这两条线后,当发送someMethod anObject不是调用的实现方法。相反,differentMethod呼吁differentObject。其他相同的类的实例不受影响;对这些原始someMethod仍然是调用的实现。方法可以有不同的名字,但他们的签名应该是相同的。

10 Limitations(限制)

10.1 Only one mock at a time can stub class methods on a given class

//一次只有一个模拟stub类方法可以在给定的类

// don't do thisid

mock1=OCMClassMock([SomeClassclass]);

OCMStub([mock1 aClassMethod]);

idmock2=OCMClassMock([SomeClassclass]);

OCMStub([mock2 anotherClassMethod]);

As mentioned above, if the mock object that added a stubbed class method is not deallocated then the stubbed method will persist, even across tests. If multiple mock objects manipulate the same class at the same time the behaviour is undefined.

译:如上所述,如果添加了一个stub类的mock对象方法不一致的方法将持续下去,甚至在测试。如果多个mock对象同时操作同一个类的行为是未定义的。

10.2 Setting up expect after stub on the same method does not work

//设置期望相同的方法stub后不工作

idmock=OCMStrictClassMock([SomeClassclass]);

OCMStub([mocksomeMethod]).andReturn(@"a string");

OCMExpect([mocksomeMethod]);

/* run code under test */

OCMVerifyAll(mock);

//willcomplainthatsomeMethodhasnotbeencalled

The code above first sets up a stub forsomeMethodand afterwards an expectation for the same method. Due to the way mock objects are currently implemented any calls tosomeMethodare handled by the stub. This means that even if the method is called the verify fails. It is possible to avoid this problem by addingandReturnto the expect statement. You can also set up a stub after the expect.

译:上面的代码首先设置一个stub someMethod后来一个期望相同的方法。由于目前mock对象的方式实现任何调用someMethod由stub。这意味着,即使方法称为验证失败。可以避免这个问题通过添加andReturn期望声明。后你也可以 在期望前设置一个stub。

10.3 Partial mocks cannot be created for certain special classes

//部分mock为某些特殊类不能被创造

idpartialMockForString=OCMPartialMock(@"Foo");

// will throw an exception

NSDate*date=[NSDatedateWithTimeIntervalSince1970:0];

idpartialMockForDate=OCMPartialMock(date);

//willthrowonsomearchitectures

It is not possible to create partial mocks for instances of toll-free bridged class, e.g.NSString, or for objects represented with tagged pointers, e.g.NSDateon some architectures. The mock object will throw a descriptive exception should you try to do this.

译:不可能为免费架桥类的实例创建局部mock,例如NSString,或者用标记表示指针的对象,例如NSDate架构。mock对象将抛出一个描述性的异常应该尝试这样做。

10.4 Certain methods cannot be stubbed or verified

//某些方法不能stubbed或验证

idpartialMockForString=OCMPartialMock(anObject);

OCMStub([partialMockclass]).andReturn(someOtherClass);

//willnotwork

It is not possible to mock a number of core runtime methods. This includesinit, class, methodSignatureForSelector: ,forwardInvocation: , respondsToSelector:, and several others.

译:不可能mock的核心运行时方法。这包括初始化、类methodSignatureForSelector:forwardInvocation:respondstoselectorismemberofclass:,和其他几个。

Note thatclassis automatically stubbed to return the original class of the object, and not the dynamic subclass used by the partial mock.

译:注意,类是自动的返回原始类的对象,而不是使用的动态子类部分模拟

10.5 Class methods on NSString and NSArray cannot be stubbed or verified

//类方法NSString和NSArray不能存根或验证。

idstringMock=OCMClassMock([NSStringclass]);

// the following will not work

OCMStub([stringMockstringWithContentsOfFile:[OCMArgany]encoding:NSUTF8StringEncodingerror:[OCMArgsetTo:nil]]);

It is not possible to stub or verify class methods onNSStringandNSArray. Trying to do so has no effect.

译:不可能onNSStringandNSArray stub类或验证方法。试图这么做没有任何影响

10.6 Methods on NSObject cannot be verified(NSObject不能验证的方法)

idmock=OCMClassMock([NSObjectclass]);

/* run code under test, which calls awakeAfterUsingCoder: */

OCMVerify([mockawakeAfterUsingCoder:[OCMArgany]]);

//stillfails

It is not possible useverify-after-runningwith methods implemented in NSObject or a category on it. In some cases it is possible to stub the method and then verify it. It is possible to useverify-after-runningwhen the method is overriden in a subclass.

译:不可能useverify-after-runningwith方法实现NSObject或一个类别。在某些情况下可以stub方法并验证。可以useverify-after-runningwhen子类的方法重载。

10.7 Private methods in core Apple classes cannot be verified

//核心苹果类中的私有方法不能得到证实

UIWindow*window=/* get window somehow */

idmock=OCMPartialMock(window);

/* run code under test, which causes _sendTouchesForEvent: to be invoked */

OCMVerify([mock_sendTouchesForEvent:[OCMArgany]]);//stillfails

It is not possible useverify-after-runningwith private methods in core Apple classes. Specifically, all methods with an underscore prefix and/or suffix in a class with either NS or UI as prefix. In some cases it is possible to stub the method and then verify it.

译:不可能stub或验证类方法NSString和NSArray。试图这么做没有任何影响。

10.8 Verify-after-running cannot use a delay(Verify-after-running不能使用延迟)

It is currently not possible to verify a method with a delay. This is currently only possible using theexpect-run-verifyapproach described below instrict mocks and expectations.

译:前不可能验证方法有延迟。这是目前只可能使用下面描述的expect-run-verify方法严格mock和期望。

10.9 Using multiple threads in tests(在测试中使用多个线程)

OCMock is not fully thread-safe. Up to version 3.2.x OCMock was not thread-aware at all. Any combination of operations on a mock object from

multiple threads was likely to cause issues and make the test fail.

译:OCMock没有完全线程安全的。3.2版本。x OCMock不是thread-aware。的任意组合操作模拟对象从多个线程可能会导致问题,使测试失败。

As of OCMock 3.3 it is still necessary to invoke all setup and verification operations from a single thread, preferrably the main thread of the test runner. It is possible, though, to use the mock object from multiple threads. The mock object can even be used from a different thread while its setup continues in the main thread. See#235for details.

译:3.3 OCMock它仍然需要从一个线程调用所有设置和验证操作,preferrably测试运行程序的主线程。这是有可能的,不过,从多个线程使用模拟对象。模拟对象甚至可以从一个不同的线程而设置仍在主线程。有关详细信息,请参阅# 235。

More detail

The test cases inOCMockTests show all uses and most edge cases.

Changes.txtcontains a chronological list of all changes.

本文由永利402游戏网站-永利402com官方网站发布于网络编程,转载请注明出处:OCMock 3 参考

关键词:

上一篇:没有了

下一篇:没有了