1

I wonder if there is a way using OCMock can invoke a class method twice separately as if the app runs two times, but in fact, only once.

I want to test a class method. Due to some static variables inside the method, the method will keep its behavior all the time once it's called. Thus I can't test different behaviors at one time.

And of course, I can't add anything else to the class if the purpose is only for testing.

Benson
  • 248
  • 3
  • 15
  • Isn't the latest version supposed to support that? – David Rönnqvist Jul 01 '13 at 09:39
  • Oh, the title is very misleading, I'll change that. – Benson Jul 01 '13 at 12:59
  • I want to test a class method, not to mock it. In fact, I need to mock sth else in the method so as to test it. But the chanllenge is the static variables in the method can only be set once. So I wonder if there is a way to invoke a class method twice saparately like the app runs twice, but in fact, only once. – Benson Jul 01 '13 at 13:03

2 Answers2

1

There is not a way to alter statically declared variables with OCMock without exposing them via Objective-C methods. You say "of course" you can't add anything to the class just for testing purpose, but this is not universally accepted. There is a an entire school of thought that believes your code itself should be designed to be tested.

- (NSInteger)someStatic
{
    static NSInteger _someStatic = 42;
    return _someStatic;
}

If you used a pattern like that that (for example, there may be better ones) you could mock your static. While this will add a method call anywhere the static is used, you may find it more important to have comprehensive testing.

Ben Flynn
  • 18,524
  • 20
  • 97
  • 142
  • 1
    See: http://stackoverflow.com/questions/15656631/accessing-static-variables-that-are-simulating-class-variables-from-unit-tests – Ben Flynn Jul 01 '13 at 14:49
0

OCMock version 2.1 has support for mocking class methods:

OCMock 2.1 released

15 March 2013

New release (2.1) which adds support for stubbing class methods and includes many contributed bug fixes. This release is compatible with Xcode 4.5/4.6.

The "Features" page on their website give some examples on how to mock a class method:

Class methods

[[[mock stub] andReturn:aValue] someClassMethod]

Tells the mock object that when someClassMethod is called on the class for which the mock object was created it should return aValue. This is the same syntax that is used to stub instance methods.

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, the intent to mock the class method must be made explicit:

[[[[mock stub] classMethod] andReturn:aValue] aMethod]

The class can be returned to its original state, i.e. all stubs will be removed:

[mock stopMocking]

This is only necessary if the original state must be restored before the end of the test. The mock automatically calls stopMocking during its own deallocation. Note: If the mock object that added a stubbed class method is not deallocated the stubbed method will persist across tests. If multiple mock objects manipulate the same class at the same time the behaviour is undefined.

David Rönnqvist
  • 56,267
  • 18
  • 167
  • 205
  • I've read this, but not what I'm looking for. Maybe the title is misleading. I'll consider a new one. – Benson Jul 01 '13 at 12:49
  • @BingchenYang Then perhaps you should give a more detailed question. What exactly are you using the mock for? Stubs? Expects? Rejects? What isn't working? – David Rönnqvist Jul 01 '13 at 12:53