Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to avoid returning mocks from a mocked object list

I'm trying out mock/responsibility driven design. I seem to have problems to avoid returning mocks from mocks in the case of objects that need a service to retrieve other objects.

An example could be an object that checks whether the bills from last month are paid. It needs a service that retrieves a list of bills. So I need to mock that billRetrievalService in my tests. At the same time I need that BillRetrievalMock to return mocked Bills (since I don't want my test to rely on the correctness of the Bill implementation).

Is my design flawed? Is there a better way to test this? Or is this the way it will need to be when using finder objects (the finding of the bills in this case)?

side note: althout Bill might be a value object candidate, the wider problem still remains when the collections aren't containing value objects (eg Users).

like image 811
koen Avatar asked Apr 20 '10 19:04

koen


1 Answers

Most of the time, if I need a mock to return another mock, I find a dependency that makes more sense in the other direction. Stated differently, mock-returning-mock usually points to a violation of the Dependency Inversion Principle.

One common exception: a factory that creates objects (as opposed to a "holder" that simply returns the same object each time). If I need to create multiple objects of the same type during my lifetime, then I might need to depend on an ObjectFactory and invoke #createObject(), then perhaps set expectations on the Objects. Even so, I would question this. It might be possible for something else one level up the call stack to create Objects for me and give them to me as needed.

In the ObjectHolder case, rather than depending on the ObjectHolder to get the Object, I prefer to depend on the Object directly and force my caller to give it to me however it wants. This respects the desirable design property of context independence.

One specific version of this issue is the "Virtual Clock" pattern. Sometimes you need to depend on virtual clock, but often it's better simply to demand a timestamp ("Instantaneous Request" pattern) or, at worst, a stream of timestamps, wherever that comes from. Tests could provide a controled stream of convenient, hardcoded timestamps, but it's also easy to turn the system clock into a stream of timestamps.

like image 53
J. B. Rainsberger Avatar answered Sep 21 '22 12:09

J. B. Rainsberger