Beyond Mock Objects - The Code Whisperer

November 23, 2013 (updated March 18, 2019) Test Doubles, Dependency Inversion Principle (DIP)


This is a companion discussion topic for the original entry at http://blog.thecodewhisperer.com/permalink/beyond-mock-objects

Injecting an object which could respond the message n_days_before would raise the abstraction level too, though I would find difficult to name that object, and it also seems too specialized. But raising the abstraction level of the clock sometimes works fine for me. Other times it doesn't, and I try to push the time related functionality into an adapter (orders_repository in this case, or by introducing an RecentOrders). Then I can test the adapter with integration tests.

Sometimes when I feel that the dependency is too "artificial", that the design smells but I am still not sure of the right direction, I just use monkey patching or isolation frameworks like PowerMock, TypeMock or any other to do the trick for me. Am not saying is recommended technique but as an intermediate step, it helps me sometimes. Thanks for a great article :-)

What I found interesting is that I read the initial sample as needing a date injected and jumped straight to "pass date as parameter". Which was the same ending point, but I think by missing the steps in between I eliminated the gradual discovery of an InstantaneousController - the problem was so "easy to solve" that I didn't give it much more thought.

I've been reading "Thinking Fast and Slow" and a good part of the book is how the intuitive part of our brain can jump to an answer in a snap and the rational part of our brain is lazy enough to just let that go by unnoticed. Similarly, I jumped to the answer and missed out on something subtle. I wonder how many date injection methods I'd write before noticing the duplication?

Great post as always. I think you just describe the road to a Domain Driven Design: business described by the domain model and everything else can and/or should be reusable functionality.

I agree strongly with the suggestion to monkey-patch or use a tool like TypeMock.

I used to build apps this way, building isolation abstractions around everything. What ruined me to this was exposure to Ruby, where everything is an object and everything can be overridden. Its flexible nature makes "injection" of dependencies a non-issue, all while cutting down the code and making testing even easier.

I mean, gosh... clear your mind for a couple minutes. Then imagine what we want to do, which is....

Get the current time.

Now open your eyes and look back at all of the code and ways being suggested to do so.

Yikes! What happened to Time.now???

Using dynamic languages like Ruby or tools like TypeMock help us get back to doing simple things in simple ways. Maybe the simplest way to get the current time is to ask for it?

Here are some alternatives in Ruby: https://gist.github.com/dar...

How does this idea scale in layered systems such as: Controller--Service--DomainObject? If it's only the DomainObject that needs the "instant" value, how would you provide it? Passing it as a method parameter requires "polluting" every method in the stack trace down to DomainObject. Alternatively, I could pass the Clock object to my Service which finds out the "instant" and passes it through to the DomainObject (but then the indirection of a Clock is only moved from one place to another). On the other hand if I use the Clock abstraction everywhere, I can inject it elegantly only to the object that really require it, avoiding the middle men to having any notion of the Clock used down the stack.

Sometimes the "instant" is an essential part of the request. For example, I want all requests timestamped. That's easy to do now, because I can register a single controller decorator (like a "before filter" in Rails) that checks now() for every request and adds it to the request. Either it passes this as a separate parameter (like in my example code here) or it merely adds this to the Request object. (You can decide to store this as a request attribute or have a new Request wrapper that includes some extra, common information.) Now it is the same as adding headers to a request. No pollution.

Your domain layer never cares about the concept of "now" or "recent", but only of "relative to some instant" or "relative to some date". This simplifies the domain and makes its behavior more referentially transparent. Easier to reason about; easier to test; still easy to use.

Of course, you will have some domain concepts that don't need to know about time at all, and their clients simply don't pass the time along. No problem there.

Any place that the domain wants a "clock", try replacing that with either a single instant or a stream of instants. I think you'll find the code to be equally clear and the tests to be less complicated. The Clock is simply a complicated way to get a single instant. :) You'll notice the difference when you write the tests.

I understand what you mean, Darren, but I strongly disagree with the way you've worded "(Ruby's) flexible nature makes "injection" of dependencies a non-issue." I think this conflates two ideas.

Yes, with Ruby/Python/Smalltalk, we can easily substitute a test double at runtime for anything anywhere anytime. I see the benefit here, especially when introducing seams to pull things apart. This puts less pressure on the programmer to build tiny things up front, because pulling big things apart requires less gymnastics than say Java or C# does.

On the other hand, I can only easily stub Time.now() *everywhere*, so I need to do this carefully. This means that we can have the singleton testing problem (I have to remember to reset the singleton to its original state at the end of my test) everywhere, all the time. Great power, great responsibility, all that.

You write, "I mean, gosh... clear your mind for a couple minutes. Then imagine what we want to do, which is.... Get the current time." In the process of refactoring, I discovered something: I don't want to get the current time, because the current time binds me to a specific context. This makes the code less easily reused. So far, this doesn't sound like much of a problem, because I'm never going to reuse "find all customers with recent, open orders", right?

OK, but what happens when I remove one piece of the context. Now I have "find all customers with order orders close to any given date". This sounds like needless complication. But wait, there's more. I notice that by extracting one tiny thing, I can have "timestamp this request", and I can have it in only one place, and in the place it belongs--before any controller handles the request--and for any request that I will ever need timestamped. For logging. For audit trails. For booking reservations. For... gosh, I don't know for what, but for *everything*. (And, by the way, in every app I ever build with this request handling technology. Ever.)

If I keep now() buried deep in my code, then I probably don't see this. I know that, because I've kept now() buried deep in my code and not seen this. I've also seen dozens of code bases in which they're kept now() buried deep in their code and not seen this.

And that's the point.

You mentioned TimeCop on twitter: a magic, implicit abstraction for the various ways Ruby implements the concept of time. I've seen this before. It's called MockEJB and did exactly the same for the JNDI context in enterprise Java applications. It solved the same problem: I can uniformly hijack an entire concept and control it. But why do we need it at all? We need it because the original idea has no useful, unifying abstraction. This leaves me interpreting your attitude as this:

"Why abstract something that's poorly abstracted? Just keep not abstracting it. It'll be fine." This is an instance of conflating simple and easy.

Maybe. In some situations, yes. Under some extreme conditions, absolutely. But we miss out on learning things when we choose this path. We almost certainly miss out on the chance to improve things. Throwing good design after bad... I can't countenance that as standard operating procedure.

I just can't.

Yes. That would be a next step. Not n_days_before(), but perhaps recent().

You said: "On the other hand, I can only easily stub Time.now() *everywhere*, so I need to do this carefully. This means that we can have the singleton testing problem (I have to remember to reset the singleton to its original state at the end of my test) everywhere, all the time. Great power, great responsibility, all that."

Have you done this in Ruby? I’d agree with you if I was suggesting to manually overwrite code, but note that in my example code I said *not* to and gave two other options: Timecop and Mocha. Both gems take care of your “singleton testing problem” by restricting the overwrites within the scope of a single test.

This means that you don’t actually have to be very responsible. If you overwrite the behavior of Time or any other object, it will be reverted in the next test.

You wrote: "I don't want to get the current time, because the current time binds me to a specific context. This makes the code less easily reused. So far, this doesn't sound like much of a problem, because I'm never going to reuse "find all customers with recent, open orders", right?... If I keep now() buried deep in my code, then I probably don't see this. I know that, because I've kept now() buried deep in my code and not seen this. I've also seen dozens of code bases in which they're kept now() buried deep in their code and not seen this."

You don’t have to get the “right” answer first. If a developer finds him or herself bound to the wrong context, the solution is easy: Change the code. If the programmer was following good programming practices (like SRP and TDD), the code will be easy to refactor.

Time is a specific problem, as it's a static call that's in multiple levels in the code. This problem would have to be fixed by following a good design process like TDD. As soon as the dev writes the first test, the dev will be forced to move into some controllable abstraction. Tests are where the dev can "see it."

I've found that looking ahead for reuse is as practical as reading tarot cards. Nobody knows what the future holds, not even the code whisperer. There are a few times when it's obvious (your example of recent versus close-to-a-date does NOT apply), but in most cases it's better to refactor a working, tested solution than trying to guess ahead.

I have done this in Ruby (for nearly a decade). Yes, stubbing/mocking using libraries like RSpec (mocha, whoever else... I only use RSpec for this now, so I don't know who the other players are) reduces the risk, and perhaps even eliminates it. Even so, that I have to stub a class-level method deep inside my code makes me nervous: why do I need to know such details? I can do it when I need to, but I've found that my designs improve when I don't need to.

You're right: I don't have to get the "right" answer first. Refactoring means exactly this, and I've been teaching this for about a decade now. We agree on this point. I agree on the rest: when we discover that our design has become problematic, we can refactor towards another one. Of course, if we don't play around with the design now, then how will we know which improvements we can make later? :)

This brings me to this feeling I have that we find ourselves in violent agreement right now. The difference seems to be that I'm using this example to explore a general concept, and you seem to have interpreted this to mean that I don't view this pragmatically. I can understand that conclusion, but you have it wrong. I merely point out in this article how even in a seemingly innocuous example like this, we have something to learn.

I agree with you that looking ahead for reuse has problems. For that reason, I push a little more and try to find that unexpected opportunity to reuse. It doesn't cost nearly as much time as you might think it does, and in refactoring almost any code, I find a dozen useful examples in the first few hours. It's like panning for gold before everyone else realises that there's gold to find.

Your final comment really puzzles me: "but in most cases it's better to refactor a working, tested solution than trying to guess ahead." I don't understand what about my solution is not working and not tested. (I haven't shown you the tests, but of course I've written them, Several times.) In other words, I don't see the dichotomy here. I've built something working and tested, and would ship it before going any further, but then I spent a few minutes going a bit further and uncovered a potentially useful reusable piece (the instantaneous request handler). Now I can be on the lookout for an opportunity to reuse it. (Of course, I've done this dozens of times, so I feel pretty confident that I'll be able to use that before too long, because I've used it several times before.)

Thank you for reminding me of that Virtual Clock article, @jbrainsberger:disqus! Yup, it fell off the Internet. It was spotted by Alfredo Chavez on http://t.co/HwQBnIvg6s.
I also posted a later copy (using Ruby for the examples) at http://ducktypo.blogspot.it....

You can apply the same idea on your Service. Your service for example can have tow methods, one with no date parameter and another with a date parameter. You can test the one with the date parameter. Your controller will then call the methods without parameter.

RecentOpenOrdersController {
....OrderService orderService;

....handleRequest() {
............orderService.getRecentOpenOrders();
....}
}

OrderService {

....getRecentOpenOrders() {
............this.getRecentOpenOrdersOrderedBefore(now());
....}

....getRecentOpenOrdersOrderedBefore(Date instant) {
............// the method easy to test
....}

}

It's not as generic as for the controller. But the idea is the same : Extract what you *can't* test (nothing more) and test the rest.

Yes. This represents an intermediate step, and might suffice, but I have found unexpected value (like the example here) in going a few steps farther.

Just wanted to drop a line to thank you for this article and many others I've read and never took the time to comment on.
I'm quite novice on the whole TDD/Good desing thing and I've certanly gone too far with Mockin All The Things. I'll keep in mind this advice for the future
Thanks again

Thanks for the article. I am pleased to read this as I actually did the exact same thing recently in Javascript while I was working on a time sensitive feature. I basically created a function that takes now and tested it very well and use an other (untested) function in the system passing new Date(). I like the simplicity and testability of the solution.

Interesting article and the technique definitely has some advantages in terms of reducing unnecessary dependency injections. However (and this is just my humble opinion) I prefer to create a seam on the call to the dependency (is this case the Date.now) extract this out to another protected method and then create a Testable version of the class which overrides that protected method in order to mock or fake the implementation for testing.

For example:

Class Foo
{
public baa() {
now = getCurrentDateTime();
// do something with now
}
protected DateTime getCurrentDateTime() {
return DateTime.now();
}
}

Class TestableFoo extends Foo
{
private DateTime customNow;

public TestableFoo(DateTime customNow) {
this.customNow = customNow;
}

protected DateTime getCurrentDateTime() {
return this.customNow;
}
}

It could be (rightly and fairly) argued that this approach is more convoluted, but I prefer it because it doesn't require the public interface of the class under test to change in any way. Whereas in your example you are exposing an extra public method now. This may be perfectly acceptable though, and I guess it's just a matter of requirements and preference.

Great technique though (it is indeed simpler than the approach I use), and thank you for sharing.

I use this technique to start pulling the design apart, and it's one of the fundamental techniques in my "Surviving Legacy Code" training course. If you now Replace Inheritance with Delegation, you arrive at a client depending on a Virtual Clock, and then you arrive at the start of this article.

_The Virtual Clock Test Pattern_, Paolo Perrotta ☞ https://ducktypo.blogspot.c...