Durch einfache Techniken zu besserer Wartbarkeit des Codes
Dennis Neumann Digitale Bibliothek Software- und Serviceentwicklung
Entschärfung des "Änderungsproblems":
Automatisiertes Testen
leicht zu testender Code ist leichter zu warten
public class Person { private String name; public void setName(String newName) { name = newName.trim(); } public String getName() { return name; } }
@Test public void shouldRemoveWhitespace() { Person personSut = new Person(); personSut.setName(" Alex "); String storedName = personSut.getName(); assertEquals("Alex", storedName); }
public class Client { public void useService() { Service srv = new Service(); srv.sendMessage("start"); //... } } // Aufruf im Produktivcode: Client c = new Client(); c.useService();
public class Client { public void useService() { Service srv = new Service(); srv.sendMessage("start"); //... } } // Aufruf im Produktivcode: Client c = new Client(); c.useService();
public class Client { private Service srv = new Service(); // for unit tests void setService(Service newSrv) { srv = newSrv; } public void useService() { srv.sendMessage("start"); //... } } // Aufruf im Produktivcode: Client c = new Client(); c.useService();
public class Client { private Service srv = new Service(); // for unit tests void setService(Service newSrv) { srv = newSrv; } public void useService() { srv.sendMessage("start"); //... } } // Aufruf im Produktivcode: Client c = new Client(); c.useService();
@Test public void shouldSendStartMessage() { // wie Produktivcode Client clientSut = new Client(); // echten Service ersetzen Service serviceMock = mock(Service.class); clientSut.setService(serviceMock);
// wie Produktivcode clientSut.useService(); // der eigentliche Test, "Sicherstellen" verify(serviceMock).sendMessage("start"); }
verify(serviceMock).sendMessage("start")
when(serviceMock.getCurrentYear()).thenReturn(3000)
when(serviceMock.sendMessage("start")).thenThrow(new ServiceIsRunningException())
public class Client { public void useService() { Service srv = new Service(); srv.sendMessage("start"); //... } } // Aufruf im Produktivcode: Client c = new Client(); c.useService();
public class Client { private Service srv; public Client() { srv = new Service(); } // for unit tests Client(Service testSrv) { srv = testSrv; } public void useService() { srv.sendMessage("start"); //... } }
public class Client { public void useService() { Service srv = new Service(); srv.sendMessage("start"); //... } } // Aufruf im Produktivcode: Client c = new Client(); c.useService();
public class Client { // keine Instanzvariable! // for unit tests Service createService() { return new Service(); } public void useService() { Service srv = createService(); srv.sendMessage("start"); //... } }
public class Client { public void useService() { Service srv = new Service(); srv.sendMessage("start"); //... } } // Aufruf im Produktivcode: Client c = new Client(); c.useService();
public class Client { private Provider serviceProvider = new Provider(); // for unit tests void setProvider(Provider newProvider) { serviceProvider = newProvider; } public void useService() { Service srv = serviceProvider.getService("local"); srv.sendMessage("start"); //... } }
public class Client { public void useService() { Service srv = new Service(); srv.sendMessage("start"); //... } } // Aufruf im Produktivcode: Client c = new Client(); c.useService();
public class Client { public void useService(Service srv) { srv.sendMessage("start"); //... } } // ABER: Aufruf im Produktivcode: Client c = new Client(); c.useService(new Service());