CreditCardProcessor processor = new CreditCardProcessor();
OfflineQueue queue = new OfflineQueue();CreditCardProcessor processor = new CreditCardProcessor();processor.setOfflineQueue(queue);
Database db = new Database();OfflineQueue queue = new OfflineQueue();queue.setDatabase(db);CreditCardProcessor processor = new CreditCardProcessor();processor.setOfflineQueue(queue);processor.setDatabase(db);
Database db = new Database();db.setUsername("username");db.setPassword("password");db.setUrl("jdbc:....");OfflineQueue queue = new OfflineQueue();queue.setDatabase(db);CreditCardProcessor processor = new CreditCardProcessor();processor.setOfflineQueue(queue);processor.setDatabase(db);
CreditCardProcessor processor = new CreditCardProcessor(?queue?, ?db?);
Database db = new Database("username", "password", "jdbc:....");OfflineQueue queue = new OfflineQueue(db);CreditCardProcessor processor = new CreditCardProcessor(queue, db);
class House { Door door; Window window; Roof roof; Kitchen kitchen; LivingRoom livingRoom; BedRoom bedRoom; House(Door door, Window window, Roof roof, Kitchen kitchen, LivingRoom livingRoom, BedRoom bedRoom){ this.door = Assert.notNull(door); this.window = Assert.notNull(window); this.roof = Assert.notNull(roof); this.kitchen = Assert.notNull(kitchen); this.livingRoom = Assert.notNull(livingRoom); this.bedRoom = Assert.notNull(bedRoom); } void secure() { door.lock(); window.close(); }}
testSecureHouse() { Door door = new Door(); Window window = new Window(); House house = new House(door, window, null, null, null, null); house.secure(); assertTrue(door.isLocked()); assertTrue(window.isClosed());}
testSecureHouse() { Door door = new Door(); Window window = new Window(); House house = new House(door, window, new Roof(), new Kitchen(), new LivingRoom(), new BedRoom()); house.secure(); assertTrue(door.isLocked()); assertTrue(window.isClosed());}
testSecureHouse() { Door door = new Door(); Window window = new Window(); House house = new House(door, window, new Roof(), new Kitchen(new Sink(new Pipes()), new Refrigerator()), new LivingRoom(new Table(), new TV(), new Sofa()), new BedRoom(new Bed(), new Closet())); house.secure(); assertTrue(door.isLocked()); assertTrue(window.isClosed());}
MVC
MVP
public CongressionalHearingView() { testimonyWidget.addModifyListener( new ModifyListener() { public void modifyText(ModifyEvent e) { presenter.onModifyTestimony(); // presenter decides action to take }});}
public class CongressionalHearingPresenter { public void onModifyTestimony() { model.parseTestimony(view.getTestimonyText()); // manipulate model } public void setWitness(Witness w) { view.setTestimonyText(w.getTestimony()); // update view }}
public void testSetWitness() { spyView = new SpyCongressionalHearingView(); presenter = new CongressionalHearingPresenter(spyView); presenter.setWitness(new Witness(“Mark McGwire”, “I didn't do it”)); assertEquals( “I didn't do it”, spyView.getTestimonyText());}
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)?
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
interface Authenticator { boolean authenticate(String username, String password);}
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(...); }}
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); }}