29 May 2012

Mocking static methods and the Gateway pattern

A year ago I started to use mocking libraries (e.g., Mockito, EasyMock, ...), both for learning something new and for testing purpose in hopeless cases.
Briefly: such a library makes it possible to dynamically redefine the behaviour (return value, thrown exceptions) of the methods of the class under test, in order to run tests in a controlled environment. It makes it possible even to check behavioural expectations for mock objects, in order to test the Class Under Test's interactions with its collaborators.
A few weeks ago a colleague asked me: "[How] can I mock a static method, eventually using a mock library?".
In detail, he was looking for a way to test a class whose code was using a static CustomerLoginFacade.login(String username, String password) method provided by an external API (an authentication custom API by a customer enterprise).
His code looked as follows:

public class ClassUnderTest {
  ...
 public void methodUnderTest(...) {
  ...
   // check authentication
   if(CustomerLoginFacade.login(...)) {
      ...
  } else {
    ...
   }
 }
}

but customer's authentication provider was not accessible from test environment: so the main (but not the only: test isolation, performances, ...) reason to mock the static login method.

A quick search in the magic mocking libraries world revealed that:
  • EasyMock supports static methods mocking using extensions (e.g, Class Extension, PowerMock)
  • JMock doesn't support static method mocking
  • Mockito (my preferred [Java] mocking library at the moment) doesn't support static method mocking, because Mockito prefers object orientation and dependency injection over static, procedural code that is hard to understand & change (see official FAQ). The same position appears even in a JMock-related discussion. PowerMock provides a Mockito extension that supports static methods mocking.
So, thanks to my colleague, I will analize the more general question "Ho can I handle external / legacy API (e.g., static methods acting as service facade) for testing purposes?". I can identify three different approaches:
  • mocking by library: we can use a mocking library supporting external / legacy API mocking (e.g, class' mocking, static methods' mocking), as discussed earlier
  • mocking by language: we can refer to the features of a dynamically typed programming language to dynamically change external / legacy API implementation / behaviour. E.g., the login problem discussed earlier can be solved in Groovy style, using the features of a language fully integrated with the Java runtime: 
CustomerLoginFacade.metaClass.'static'.login = {
              return true;
}; 

Such an approach can be successfully used when CustomerLoginFacade.login's client code is Groovy code, not for old Java client code.
  • Architectural approach: mocking by design. This approach refers to a general principle: hide every external (concrete) API behind an interface (i.e.: coding on interfaces, not on concrete implementation). This principle is commonly knows as dependency inversion principle.
So, we can solve my colleague's problem this way: first, we define a login interface:

public interface MyLoginService {
 public abstract boolean login(final String username, final String password);
}

Then, we refactor the original methodUnderTest code to use the interface:

public class ClassUnderTest {
  private MyLoginService loginService;
 // Collaborator provided by Constructor injection (see here for
 //  a discussion about injection styles)
 public ClassUnderTest(final LoginService loginService) {
  this.loginService = loginService;
 }   
 ...
 public void methodUnderTest(...) {
  ...
   // check authentication
   if(loginService.login(...)) {
      ...
  } else {
    ...
   }
 }
}


So, for testing pourposes, we can simply inject a fake implementation of the MyLoginService interface:

public void myTest() {
 final ClassUnderTest cut = new ClassUnderTest(new FakeLoginService());
 cut.methodUnderTest(..., ...);
 ...
}


where FakeLoginService is simply
 
public class FakeLoginService implements MyLoginService {
 public boolean login(final String username, final String password) {
  return true;
 }
}

and the real, pruduction implementation of the interface looks simply like this:

public class RealLoginService implements MyLoginService {
 public boolean login(final String username, final String password) {
  return CustomerLoginFacade.login(username, password);
 }
}


Ultimately, the interface defines an abstract gateway to the external authentication API: changing the gateway implementation, we can set up a testing environment fully decoupled from real customer' authentication provider
.
IMHO, i prefer the last mocking approach: it's more object oriented, and after all... my colleague called me once the more OO person I know :-). I find this approach more clean and elegant: it's built only upon common features of programming languages and doesn't refer to external libraries nor testing-oriented dynamic languafe features.
In terms of design, too, I think it's a more readable and more reusable solution to the problem, which allows a clearer identification of responsibilities of the various pieces of code: MyLoginService defines an interface, and every implementation represents a way to implement it (a real-life (i.e.: production) implementation versus the fake one).

However, method mocking (by library or by language, doesn't matter) is in certain, specific situations a very useful technique, too, especially when code that suffers static dependencies (ClassUnderTest in our example) is an example of legacy code, designed with no testing in mind, and is eventually out of developer control.
[Incidentally: the solution adopted by my colleague was just that I have proposed (i.e., mocking by design)]

Credits: thanks to Samuele for giving me cause to analyze such a problem (and for our frequent and ever interesting design-related discussion). Thanks to my wife for hers valuable support in writing in pseudo-English

24 May 2012

Eloquent JavaScript - An opinionate guide to programming

Eloquent JavaScript - An opinionate guide to programming - Marijn Haverbeke, 2011

Interesting and useful guide to Javascript, whose "opinionate" approach can reconcile with this loved-heated language. I found extremely interesting the sections about functional programming and object oriented programming: finally I've found a systematic presentation of OOP in Javascript!

21 May 2012

How to automatically test Java Console

Some weeks ago, during a workroom lesson in University, I've faced a typical TDD-addicted dilemma: how can I test driven develop a console-based Java application?
The main problem is clearly how to automatically interact with the application, which relies to System.in for user input and to System.out for user output.
You can use System.setIn and System.setOut methods, of course: but this is IMHO a dirty solution to the console-interaction testability problem, which can be resolved in a cleaner way referring to the dependency inversion principle, ubiquitous in test driven design: rather than directly referring to concrete System.in and System.out streams (this reference is concrete because it's direct, not because it points to a concrete class: InputStream is really an abstract class), the console-based application should reference to some abstraction that encapsulates standard I/O streams dependency - for example to Scanner (for user input) and PrintStream (for user ouput: again, direct reference to System.out is concrete because it's direct, not because it points to something concrete).
So, application behaviour can be encapsulated into a classe having a constructor like this:
 
public HelloApp(Scanner scanner, PrintStream out)

The application main method instances such a class and invokes a method thar triggers application logic execution, simply providing Scanner and PrintStream that wrap standard I/O streams:

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        scanner.useDelimiter(System.getProperty("line.separator"));
        
        HelloApp app = new HelloApp(scanner, System.out);
        app.run();
}

Testing code, however, can provide to HelloApp testing oriented instances of Scanner and PrintStream:

final Scanner scanner = new Scanner("Duke y Goofy y Donald n");
scanner.useDelimiter(" "); 
 
ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream();
PrintStream out = new PrintStream(outputBuffer); 
 
final HelloApp app = new HelloApp(scanner, out);
app.run();
 
final String output = outputBuffer.toString(); 
// Assertions about outputBuffer content:
assertTrue(output.startsWith("Welcome to HelloApp!")); 

So, we have gracefully decoupled application logic from console-based user interactions, providing a solid framework for automated application testing and, even more satisfying for TDD addicted, for Test Driven Development.


Code repository can be cloned using git:
git clone https://bitbucket.org/pietrom/automatically-testing-the-console.git

16 May 2012

JNDI name duplication problem chez WebSphere

Yesterday a colleague and I have faced a subtle problem deploying a suite of enterprise applications on WebSphere Application Server - version 6.1.
The problem manifested itself with a marshalling error when a webapp called a service exposed as an EJB in the same enterprise application: this was very annoying due to two main aspects:
  1. there was no duplication, between webapp and EJB module, fot the classes involved in the call
  2. the issue seemed to occur randomly: not for all calls (and never for some), not always for the same call (apparently depending to application restart)
After a few hours of stop-and-start-and-read-the-log nightmare, we discovered that at the root of the problem was a JNDI name duplication between EJBs published by two different applications of the suite: these applications are based on the same infrastructural framework, and the framework published some framework services using a fixed JNDI name. This was clearly an error in suite packaging, but... WebSphere did not report in any way this name collision, deployed without errors nor warnings both the applications, and the duplicated JNDI name was associated with an implementation of the service or with the other, depending to starting order of the apps. So:
  1. the marshalling problem appeared when the webapp from an EAR called the service published by the other application
  2. the issue occurred only for the EJB with the duplicated name, not for the others; and coccurred or did not depending to the starting order
The solution was quite simple: changing the JNDI name of  one of the twins services.
But... why the application server did not give any error when deploying an EJB using an already-in-use JNDI name, as do for example JBoss and BEA Weblogic application servers?

Definitely something to remember!