I have one singleton class written in Objective C which is being used in helper class which is also written in Objective C. I am writing a test case for the helper class, but instead of making changes directly to singleton class methods, I want to create a mock singleton class, but I'm not sure how to do that. I don't want to make any changes in helper class either like creating a init method which takes singleton class object and initialise it like mention on other threads for test cases for singleton class.
Thanks for looking the question.
You can use OCMock for mocking objects in your project OCMock
Then you can mock your singleton like this
YOUR_SINGLETON *mock = OCMClassMock([YOUR_SINGLETON class]);
And stub function like this
OCMStub([(id) mock YOUR_FUNCTION:PARAMETER]).andReturn(VALUE_FOR_TEST_CASE);
Related
I'm new to method swizzling and now I'd like to do a little more with that on iOS:
Is there an easy/elegant way in Objective-C to redirect all calls of an existing class (ClassA) to another class (ClassB, provided it has the exact same methods). I know it's possible to do so with a single method (method swizzling), but what about an entire class?
getting the list of all the class's methods and swizzling them one by one?
swizzling only the init method of the class?
any other way?
The class I want to replace has a lot of static methods and I don't want to touch the original code.
I have a Utility class with some class methods.
#interface DataValidator : NSObject
+ (BOOL)foo;
#end
The usage of the class is inside other classes, say NetworkManager, DBHandler etc. And since there are no instance methods in Utility class, there is no need for any class to create an instance of Utility class. Rather they directly make the calls like this
[Utility foo];
When writing tests for NetworkManager/DBHandler, is it possible to mock Utility and stub foo so all calls made to it return the mocked response.
If I mock the Utility class in NetworkManager class tests, the NetworkManager code still calls original method instead of the stubbed one.
This only works if I directly call [Utility foo] from inside the tests, but thats not useful in my case.
Looks like OCMock 3 has a way to mock Class methods:
http://ocmock.org/reference/#mocking-class-methods
An example from that page:
id classMock = OCMClassMock([SomeClass class]);
OCMStub([classMock aClassMethod]).andReturn(#"Test string");
// result is #"Test string"
NSString *result = [SomeClass aClassMethod];
I wasn't able to achieve this. What I ended up doing is converting the class methods to instance methods and then mocking those.
I’m using OCMock, and attempting to test a class with two class methods. I’d like to stub one in order to write a test for the other, so I’d normally use an OCMPartialMock. However, if I do this, I can’t call the class method since OCMPartialMock uses an instance of the class, not the class itself. If I use OCMClassMock, it’ll lose the implementation of the method I want to test.
In summary: I have two class methods, and I’d like to stub one but retain the ability to call the other, using OCMock. How can I achieve this?
Found the answer: need to use an OCMClassMock, and since it’s swizzled the class, call the other class method on the class itself, not on my mocked id version.
sample code:
#interface MyClass: NSObject
+ (void)hello;//this is a class method
#end
id mock = OCMClassMock([MyModel class]);
[OCMStub([mock hello]) andDo:^(NSInvocation *invocation) {
NSLog(#"hello everyone");
}];
[MyModel hello]; //it will print 'hello everyone'
Whenever I try to put NSData.dataWithContentsOfURL(), Xcode doesn't recognise it. The only one it recognizes is
NSData.dataWithContentsOfMappedFile(<#path: String#>)
Here's what it looks like:
When Swift imports interfaces from ObjC, it treats factory class methods that use Cocoa naming conventions into initializers.
In general, a class method on NSThing called thingWithNumber: turns into the initializer init(number:) and you call it with initializer syntax and the name of the class: NSThing(number: 42). In the case of classes that have both a thingWithNumber:-style class method and an initWithNumber:-style instance method that does the same thing, both map to the same Swift initializer.
In this case, dataWithContentsOfURL: and initWithContentsOfURL: become init?(contentsOfURL:). You can find these conversions and more by looking at the Swift interface for a class in Xcode (command-click the class name) or in the class documentation.
Is ok if I add class methods that I need over all my project in the application delegate?
and then I import the delegate in the current UIViewController and I invoke the method: [MyAppDelegate classMethod];
Is a good approach ?
thanks
I set up an APP_DELEGATE macro that is defined as:
#define APP_DELEGATE ((AppDelegate *)[[UIApplication sharedApplication] delegate])
... so when I need to use it, I just code:
[APP_DELEGATE someInstanceMethod];
So yes, I use instance methods instead (for simplicity). Just define this macro in your AppDelegate.h and include it wherever you need it.
I think it should be fine, but I would only do it if it a) makes sense, and b) is truly the only place for that method. I'd think long and hard about whether that functionality belongs in the delegate or in some other singleton or shared class.
I would say that it's an acceptable approach but I would not recommend it. It depends on what the methods you are taking about do. For example, if you want to be able to access your data model from everywhere in your app, it's better to use a singleton, so that you separate the model completely from the rest of the app.
it's depending upon ur app needs or context.
if u r going to access class variables then u can choose class methods to create.
but u cannot access the instance variables.
but my choice is instance method which will operate on both class variable and instance variable.
The difference between class methods and instance methods are
Class methods
Operate on Class variables (they can not access instance variables)
Do not require an object to be instantiated to be applied
Sometimes can be a code smell (some people who are new to OOP use as a crutch to do Structured Programming in an OO enviroment)
Instance methods
Operate on instances variables and class variables
Must have an instanciated object to operate on