Designing For Testability Characteristics of Testable Code

• Highly cohesive • Loosely coupled – Dependencies minimized • Dependency injected • Minimal use of static methods and final methods • Static methods contain few parameters • Complex object creation logic is placed in Factories and/or Builders Features that are Difficult to Automate

• Dependencies created by the class under test – Prevents mocking / unit isolation • Final methods – Can’t be overridden by mocks or other types of test doubles • Static methods – Can’t be overridden by mocks or other types of test doubles • Code that contains complex object creation logic (especially if it creates complex object graphs) • GUI / View Code Strategies

• Test-Driven Development • • Use of configurable factories with simple (preferably no-argument) constructors • In-class wrapper methods for calls to static method • Use of MVC / MVP with view interfaces Problem: Dependencies Created by the Class Under Test public class PayrollProcessor { private DatabaseService dbService;

public PayrollProcessor() { dbService = new DatabaseService(); }

public double getTaxAmount(String employeeID) { Employee emp = dbService.getEmployee(employeeID);

double taxAmount = 0;

// Some complicated code that uses information from // 'emp' to calculate taxes

return taxAmount; } } Solution

• Dependency Injection • Mocking of the DatabaseService instance in the test public class PayrollProcessor2 { private DatabaseService dbService;

public PayrollProcessor2(DatabaseService dbService) { this.dbService = dbService; }

public double getTaxAmount(String employeeID) { Employee emp = dbService.getEmployee(employeeID);

double taxAmount = 0;

// Some complicated code that uses information from 'emp' to // calculate taxes

return taxAmount; } } Solution: Setter Injection

public class PayrollProcessor3 { private DatabaseService dbService;

public void setDbService(DatabaseService dbService) { this.dbService = dbService; }

public double getTaxAmount(String employeeID) { Employee emp = dbService.getEmployee(employeeID);

double taxAmount = 0;

// Some complicated code that uses information from 'emp' to // calculate taxes

return taxAmount; } } The “Mock Object” design pattern

• Allows “mock objects” to be inserted anywhere in a program

• Allows a class to be isolated from its dependencies during , or for other reasons (e.g., a class I depend on doesn’t exist yet, or I want to avoid calling it for some reason)

• Supports “fault injection” – Cause the software to fail at points where it normally wouldn’t to test error handling code

• Easy to generate with frameworks such as Mockito and EasyMock The “Mock Object” design pattern

• Mock objects can simulate the behavior of complex, real (non-mock) objects and are therefore useful when a real object is impractical or impossible to incorporate into a unit test. • If an object has any of the following characteristics, it may be useful to use a mock object in its place: – supplies non-deterministic results (e.g., current time or current temperature); – has states that are difficult to create or reproduce (e.g., a network error); – is slow (e.g., a complete , which would have to be initialized); – does not yet exist or may change behavior; – would have to include information and methods exclusively for testing purposes (and not for its actual task). • Mock object method implementations can contain assertions of their own. This means that a true mock, in this sense, will examine the context of each call— perhaps checking the order in which its methods are called, perhaps performing tests on the data passed into the method calls as arguments. Mock Object Creation with Mockito public class PayrollProcessorTest { @Test public void testGetTaxAmount() { DatabaseService mockDBService = Mockito.mock(DatabaseService.class);

Employee mockEmployee = Mockito.mock(Employee.class); Mockito.doReturn(mockEmployee).when( mockDBService.getEmployee(Mockito.anyString()));

// Mockito.when calls to setup mockEmployee to do what we will write // our test to expect

PayrollProcessor2 processor = new PayrollProcessor2(mockDBService);

// Code to test the getTaxAmount() method assuming that the // DatabaseService returns an employee object that does what we mocked // our mockEmployee to do } } Dependency Injection • Programming style that allows objects to receive their dependencies instead of creating them • Makes your design more flexible (dependencies are no longer “hard- coded” into the class that uses them • Facilitates testing by making it easy for a test to mock a dependency • Choose a “Dependency Injection Container” – Spring, Ninject, Google Guice, etc. • Configure your dependency injection container with a mapping from abstract interfaces to concrete classes that implement them • Create objects by asking the dependency injection container for an implementation of an abstract • Allows program code to depend on abstract interfaces, and not on concrete classes • Allows mock objects to be easily inserted anywhere in the code Problem: Final Methods

• Mocking frameworks mock interfaces by creating their own implementations • They mock classes by creating subclasses • Final methods cannot be sub-classed, so most mocking frameworks cannot mock them • Final methods can be tested, but if the dependency you want to mock has a final method, you typically cannot replace that method with a mock implementation – Can’t do this: Mockito.doReturn(xyz).when(mockObject.myFinalMethod()) Solutions

1. Minimize the use of final methods (warning: virtual methods are slower than final methods) 2. Use a mocking framework that can mock final methods (i.e. PowerMock) 1. PowerMock is slow 2. Generally considered bad practice to use it Problem: Static Methods

• Similar problems as final methods – Can’t be mocked by most mocking frameworks • Static methods are testable, but classes that have dependencies on them are difficult to test Solutions

1. Minimize the use of static methods 2. Wrap calls to static methods in non-static methods in the dependent class 3. Use a mocking framework that can mock static methods (i.e. PowerMock) Problem: Code that Contains Complex Creation Logic

• Similar to the general problem of classes that create their own dependencies • Difficult to use dependency injection Solution

• Use a factory to create the dependency object(s) • Use a non-static ‘get…’ method to create the object – Makes the entire factory mockable

public class ServiceFactory { public DatabaseService getDatabaseService() { DatabaseService dbService = null;

// Complex logic to create and initialize a // database service instance.

return dbService; } } Factory in Greater Detail Problem: GUI / View Code

• GUIs are difficult to test using test automation tools • GUIs change frequently (making GUI test code brittle) • GUI automation tools (i.e. Selenium for browser-based applications) are somewhat flaky • GUI tests that automate and mimic user behavior are slow (due to screen creation and redraws) Solution

• Use an MVC / MVP design – Separate actual view code from what can go in controller/presenter and model classes that are easier to test

• Use interfaces for your views and make controllers/presenters only depend on the view interfaces (not the actual views) – Allows mocking of the view code – Will still need a few system level tests (automated or manual) but most view code can be tested without actually generating the view