TotT: Keep Your Fakes Simple

When scientists in California tried to raise condors in captivity, they ran into a problem. The chicks wouldn't eat from the researchers' hands; they wanted a mother condor to feed them. So the scientists got a puppet. To the chicks, it looked like their mother's head was feeding them—but inside was the same scientist's hand.

Consider a contrived example based on that:

TEST_F(BabyCondorTest, EatsCarrion) {
  FakeCondor mother;
  scoped_ptr carrion;
  BabyCondor* pchick = &chick_;
  mother.Imprint(vector(&pchick, &pchick + 1)); // just one chick
  while(!chick_.HasFood()) {
    mother.Eat(); // disposes of any food the mother kept for herself
    mother.Scavenge(carrion.reset(new FakeCarrion)); // finds new food
    mother.RandomlyDistributeFoodAmongYoungAndSelf(); // feeds baby or mom
  }
  chick_.Eat();
  EXPECT_TRUE(carrion->WasEaten());
}



Something is wrong here—that was a lot of setup! The general-purpose FakeCondor replicates too much functionality from the full class. The researchers' puppet didn't scavenge its own carrion, so why should ours? We just want to test that the baby Eats. We condense various motherhood behaviors, such as giving food, into single method calls by extracting a role interface. (If we couldn't change Condor, we would also write an adapter.)

class CondorMotherhoodRoleInterface {
 public:
  virtual Carrion* GiveFood() = 0;
  virtual SomeReturnTypes* OtherMomBehaviors() = 0;
};



Then we write a single-use fake which provides only behaviors we need for this particular test.

class CondorFeedingPuppet: public CondorMotherhoodRoleInterface {
 public:
  virtual Carrion* GiveFood() { return test_carrion_; }
  virtual SomeReturnTypes* OtherMomBehaviors() { return NULL; }
  Carrion* test_carrion_; // public var is tolerable in a one-off object
};

TEST_F(BabyCondorTest, EatsCarrion) {
  CondorFeedingPuppet mother; FakeCarrion test_carrion;
  mother.test_carrion_ = &test_carrion;
  chick_.ReceiveFood(&mother);
  chick_.Eat();
  EXPECT_TRUE(test_carrion.WasEaten());
}



This highly-focused fake is easy and quick to write, and makes the test much simpler and more readable. Don't overestimate the complexity of your dependencies! Often a very simple fake is the best.

Remember to download this episode of Testing on the Toilet and post it in your office.

Permalink | Links to this post | 0 comments

When to use Dependency Injection

by Miško Hevery

A great question from the reader...

The only thing that does not fully convince me in your articles is usage of Guice. I'm currently unable to see clearly its advantages over plain factories, crafted by hand. Do you recommend using of Guice in every single case? I strongly suspect, there are cases, where hand-crafted factories make a better fit than Guice. Could you comment on that (possibly at your website)?

I think this is multi-part question:

  1. Should I be using dependency-injection?

  2. Should I be using manual dependency-injection or automatic dependency-injection framework?

  3. Which automatic dependency-injection framework should I use?


Should I be using dependency-injection?

The answer to this question should be a resounding yes! We covered this many times how to think about the new-operator, singletons are liars, and of course the talk on dependency-injection.

Dependency injection is simply a good idea and it helps with: testability; maintenance; and bringing new people up to speed on new code-base. Dependency-injection helps you with writing good software whether it is a small project of one or large project with a team of collaborators.

Should I be using manual dependency-injection or automatic dependency-injection framework?

Whether or not to use a framework for dependency injection depends a lot on your preferences and the size of your project. You don't get any additional magical powers by using a framework. I personally like to use frameworks on medium to large projects but stick to manual DI with small projects. Here are some arguments both ways to help you make a decision.

In favor of manual DI:

  • Simple: Nothing to learn, no dependencies.

  • No reflection magic: In IDE it is easy to find out who calls the constructors.

  • Even developers who do not understand DI can follow and contribute to projects.


In favor of automatic DI framework:

  • Consistency: On a large team a lot can be said in doing things in consistent manner. Frameworks help a lot here.

  • Declarative: The wiring, scopes and rules of instantiation are declarative. This makes it easier to understand how the application is wired together and easier to change.

  • Less typing: No need to create the factory classes by hand.

  • Helps with end-to-end tests: For end-to-end tests we often need to replace key components of the application with fake implementations, an automated framework can be of great help.


Which automatic dependency-injection framework should I use?

There are three main DI frameworks which I am aware off: GUICE, Pico Container and Spring.

I work for Google, I have used GUICE extensively therefor my default recommendation will be GUICE. :-) However I am going to attempt to be objective about the differences. Keep in mind that I have not actually used the other ones on real projects.

Spring was first. As a result it goes far beyond DI and has everything and kitchen sink integrated into it which is very impressive. The DI part of Spring has some differences worth pointing out. Unlike GUICE or Pico, Spring uses XML files for configuration. Both are declarative but GUICE is compiled and as a result GUICE can take advantage of compiler type safety and generics, which I think is a great plus for GUICE.

Historically, Spring started with setter injection. Pico introduced constructor injection. Today, all frameworks can do both setter and constructor injection, but the developers using these frameworks still have their preferences. GUICE and Pico strongly prefer constructor injection while Spring is in the setter injection camp. I prefer constructor injection but the reasons are better left for another post.

Personally, I think all of the three have been around for a while and have proven themselves extensively, so no matter which one you chose you will benefit greatly from your decision. All three frameworks have been heavily influenced by each other and on a macro level are very similar.

Your milage may very.

Permalink | Links to this post | 10 comments

TotT: Use EasyMock

Welcome back! We trust you all had a good holiday season and are ready for more TotTs -- Dave



Most of us are aware that mock and stub objects can make testing easier by isolating the class under test from external dependencies. This goes hand-in-hand with dependency injection. Writing all these classes can be a pain though.

EasyMock provides an alternative. It dynamically implements an interface which records and replays your desired behavior. Let's say you want to model an ATM interface:

public interface Atm {
  boolean enterAccount(String accountNumber);
  boolean enterPin(String pin);
  boolean enterWithdrawalAmount(int dollars);
}



It is pretty easy to mock this interface. Still, every mock has to implement all three methods, even if you only need one. You also need a separate mock for each set of inputs. With EasyMock, you can create mocks as you need them, recording and replaying your expectations:

public void testAtmLogin() {
  Atm mockAtm = createMock(Atm.class); // 1
  EasyMock.expect(mockAtm.enterAccount("MyAccount")).andReturn(true); // 2
  EasyMock.expect(mockAtm.enterPin("1234")).andReturn(true); // 3
  EasyMock.replay(mockAtm); // 4
  Account account = new Account();
  account.login(mockAtm); // 5
  assertTrue(account.isLoggedIn());
  EasyMock.verify(mockAtm); // 6
}



We tell EasyMock to create a dynamic proxy implementing Atm (1), which starts in record mode. Then we record two method calls along with the expected results (2 and 3). The replay() call tells EasyMock to stop recording (4). After that, calls on the object return the set values. If it gets a call it does not expect, it throws an Exception to fail fast. Account now uses the mock as if it were the real thing (5). The verify() method checks to see if the mock actually received all the calls you expect (6). It really is that simple. If we want to simulate failure, we can set up another test to return false from one of the method calls.

EasyMock has lots more capabilities as well. It can throw exceptions. It also can record multiple calls to the same method returning the same or different results. You also can create stub expectations and nice mocks so you don't have to record every expected call. You also can create several mocks, and even nest them to test classes with complex dependencies. Beware, though, this often creates brittle tests, and is a sign the class under test needs refactoring.

Basic EasyMock only mocks interfaces, but there is an EasyMockClassExtension that mocks non-final classes when you really must. See the EasyMock documentation at the link below for details.

Remember to download this episode of Testing on the Toilet and post it in your office.

Permalink | Links to this post | 7 comments

Interfacing with hard-to-test third-party code

by Miško Hevery

Shahar asks an excellent question about how to deal with frameworks which we use in our projects, but which were not written with testability in mind.

Hi Misko, First I would like to thank you for the “Guide to Writing Testable Code”, which really helped me to think about better ways to organize my code and architecture. Trying to apply the guide to the code I’m working on, I came up with some difficulties. Our code is based on external frameworks and libraries. Being dependent on external frameworks makes it harder to write tests, since test setup is much more complex. It’s not just a single class we’re using, but rather a whole bunch of classes, base classes, definitions and configuration files. Can you provide some tips about using external libraries or frameworks, in a manner that will allow easy testing of the code?

-- Thanks, Shahar

There are two different kind of situations you can get yourself into:


  1. Either your code calls a third-party library (such as you calling into LDAP authentication, or JDBC driver)

  2. Or a third party library calls you and forces you to implement an interface or extend a base class (such as when using servlets).


Unless these APIs are written with testability in mind, they will hamper your ability to write tests.

Calling Third-Party Libraries

I always try to separate myself from third party library with a Facade and an Adapter. Facade is an interface which has a simplified view of the third-party API. Let me give you an example. Have a look at javax.naming.ldap. It is a collection of several interfaces and classes, with a complex way in which you have to call them. If your code depends on this interface you will drown in mocking hell. Now I don't know why the API is so complex, but I do know that my application only needs a fraction of these calls. I also know that many of these calls are configuration specific and outside of bootstrapping code these APIs are cluttering what I have to mock out.

I start from the other end. I ask myself this question. 'What would an ideal API look like for my application?' The key here is 'my application' An application which only needs to authenticate will have a very different 'ideal API' than an application which needs to manage the LDAP. Because we are focusing on our application the resulting API is significantly simplified. It is very possible that for most applications the ideal interface may be something along these lines.
interface Authenticator {
boolean authenticate(String username,
String password);
}

As you can see this interface is a lot simpler to mock and work with than the original one as a result it is a lot more testable. In essence the ideal interfaces are what separates the testable world from the legacy world.

Once we have an ideal interface all we have to do is implement the adapter which bridges our ideal interface with the actual one. This adapter may be a pain to test, but at least the pain is in a single location.

The benefit of this is that:

  • We can easily implement an InMemoryAuthenticator for running our application in the QA environment.

  • If the third-party APIs change than those changes only affect our adapter code.

  • If we now have to authenticate against a Kerberos or Windows registry the implementation is straight forward.

  • We are less likely to introduce a usage bug since calling the ideal API is simpler than calling the original API.


Plugging into an Existing Framework

Let's take servlets as an example of hard to test framework. Why are servlets hard to test?

  • Servlets require a no argument constructor which prevents us from using dependency injection. See how to think about the new operator.

  • Servlets pass around HttpServletRequest and HttpServletResponse which are very hard to instantiate or mock.


At a high level I use the same strategy of separating myself from the servlet APIs. I implement my actions in a separate class
class LoginPage {
Authenticator authenticator;
boolean success;
String errorMessage;
LoginPage(Authenticator authenticator) {
this.authenticator = authenticator;
}

String execute(Map<String, String> parameters,
String cookie) {
// do some work
success = ...;
errorMessage = ...;
}

String render(Writer writer) {
if (success)
return "redirect URL";
else
writer.write(...);
}
}

The code above is easy to test because:

  • It does not inherit from any base class.

  • Dependency injection allows us to inject mock authenticator (Unlike the no argument constructor in servlets).

  • The work phase is separated from the rendering phase. It is really hard to assert anything useful on the Writer but we can assert on the state of the LoginPage, such as success and errorMessage.

  • The input parameters to the LoginPage are very easy to instantiate. (Map<String, String>, String for cookie, or a StringWriter for the writer).


What we have achieved is that all of our application logic is in the LoginPage and all of the untestable mess is in the LoginServlet which acts like an adapter. We can than test the LoginPage in depth. The LoginSevlet is not so simple, and in most cases I just don't bother testing it since there can only be wiring bug in that code. There should be no application logic in the LoginServlet since we have moved all of the application logic to LoginPage.

Let's look at the adapter class:
class LoginServlet extends HttpServlet {
Provider<LoginPage> loginPageProvider;

// no arg constructor required by
// Servlet Framework
LoginServlet() {
this(Global.injector
.getProvider(LoginPage.class));
}

// Dependency injected constructor used for testing
LoginServlet(Provider<LoginPage> loginPageProvider) {
this.loginPageProvider = loginPageProvider;
}

service(HttpServletRequest req,
HttpServletResponse resp) {
LoginPage page = loginPageProvider.get();
page.execute(req.getParameterMap(),
req.getCookies());
String redirect = page.render(resp.getWriter())
if (redirect != null)
resp.sendRedirect(redirect);
}
}

Notice the use of two constructors. One fully dependency injected and the other no argument. If I write a test I will use the dependency injected constructor which will than allow me to mock out all of my dependencies.

Also notice that the no argument constructor is forcing me to use global state, which is very bad, but in the case of servlets I have no choice. However, I make sure that only servlets access the global state and the rest of my application is unaware of this global variable and uses proper dependency injection techniques.

BTW there are many frameworks out there which sit on top of servlets and which provide you a very testable APIs. They all achieve this by separating you from the servlet implementation and from HttpServletRequest and HttpServletResponse. For example Waffle and WebWork

Permalink | Links to this post | 1 comments