Testing Methods That Call Methods of Other Objects

112 views
Skip to first unread message

Scotty C

unread,
Jan 16, 2014, 4:18:11 PM1/16/14
to clean-code...@googlegroups.com
I seem to have hit an interesting road block recently. In trying to implement a high level part of my system, it finally came time to start calling methods of objects that are explicitly named, and I'm having a hard time figuring out how to test these. Let me give a short example.

First, I had the controller directly create the corresponding interactor. Not only did that break the dependency rule of the controller only knowing of the input port boundary, but I couldn't figure out how to test that, because in calling main on the interactor, too much work is being done.
public class Controller
{
    public void doSomething()
    {
        Interactor interactor = new Interactor;
        interactor.main();
    }
}

That seemed like an easy fix. I'd could just dependency inject the interactor, which would fix both problems. Now the controller was testable, because I could mock the interactor and not have it do all of its normal work.
public class Controller
{
    public void doSomething(InputPort interactor)
    {
        interactor.main();
    }
}

Now, having the controller using proper abstractions, the same problem hit me again in the next layer up. I needed some way to call the controller associated with the current action/request, so I tried to use builder object to create the controller and give it the interactor it requires.
public class Builder
{
    public void buildController
    {
        Controller controller = new Controller;
        controller.doSomething(new Interactor);
    }
}

And once again, I have the exact same problem. By naming the class explicitly and calling a method, I can't test buildController because all heck breaks loose when doSomething is called.

So I have two questions.
  1. How do I go about testing methods that call other, un-mockable methods?
  2. How do you guys call the controllers in your system in such a way that they don't know too much, and are testable?

Jon Reid

unread,
Jan 17, 2014, 5:19:56 PM1/17/14
to clean-code...@googlegroups.com
Looks like you need Dependency Injection. Basically, instead of calling "new Interactor", you'd need one of two approaches:

- Pass in the Interactor to the Controller sometime before doSomething() does its work, or
- Pass in a factory that can create the Interactor on-demand

Do that, and suddenly everything becomes testable. I just did presentations on this in Warsaw and Berlin. Although my code examples are in Objective-C, I explain the examples for folks who work in other languages.

- Jon Reid


--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.
To post to this group, send email to clean-code...@googlegroups.com.
Visit this group at http://groups.google.com/group/clean-code-discussion.

Scotty C

unread,
Jan 20, 2014, 7:56:46 PM1/20/14
to clean-code...@googlegroups.com
Okay, thanks for the advice. Nice video, too. :)
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discussion+unsub...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages