OCMock validates the object and calls the method

I finally impose TDD on the project that I am working on, and work around the world ... I know the code I want, but not how to test it :)

The implementation I'm looking for is:

- (void) doSomething { FooBuilder *foo = [[FooBuilder alloc] init]; [foo doSomethingElseWithCompletionBlock:^{ [self somethingDone]; }]; } 

Therefore, I want my test to verify that: a) the test method selects a new FooBuilder and b) which then calls the method on the new object.

How should I do it? I started from the path, trying to scoff at the method of the alloc class, but quickly determined that this path was crazy.

Note. I do not test FooBuilder myself with this test, just collaboration there.

+4
source share
2 answers

Typically, dependency injection is used to create a fully formed object, saying, "instead of asking for this object, here you go, use this." But in this case, we want to create an instance of a new object. So instead of entering an object, all we need to do is enter a class. "Instead of creating a specific class, here you go, create one of them."

There are two main forms of dependency injection: “constructor injection” (I will stick with the term “constructor”, although Objective-C divides this into distribution and initialization) and “property injection”.

To inject a constructor, specify the class in the initializer:

 - (instancetype)initWithFooBuilderClass:(Class)fooBuilderClass; 

To inject properties, specify the class in the property:

 @property (nonatomic, strong) Class fooBuilderClass; 

The constructor input is clearer because it makes the dependency obvious. But you may prefer nesting properties. Sometimes I start one path and refactor in relation to another, changing my mind.

In either case, you can have a default initializer that either calls -initWithFooBuilderClass: or sets the property to [FooBuilderClass class] .

Then doSomething will start as follows:

 - (void)doSomething { id foo = [[self.fooBuilderClass alloc] init]; ... 
+1
source

I ended up FooBuilder at this by adding a new class method to FooBuilder , which takes a completion block as an argument. So I actually moved the instance and method call from my object to the test object. Now I can make fun of a method call of one class.

I think it ends a little better than what I started with; the details that should be created by FooBuilder are now hidden from users of this class. It is also quite simple.

It has the property that it maintains a strong connection between my test object and the FooBuilder class. Maybe it will bite me along the way, but I bet YAGNI that she will not.

0
source

Source: https://habr.com/ru/post/1494002/


All Articles