ich mit einigen Prototyp-Code begann, die in diese Richtung geht:Ist die Testimplementierung beim Entwerfen der Klasse, die die externe API aufruft, korrekt?
// Omitted most definitions, return values checks, etc.
// The real code is much bigger and uglier.
serverId = socket(AD_INET, SOCK_STREAM, PROTO_ANY);
setsockopt(serverId, SOL_SOCKET, SO_REUSEADDR, &reuseAddrOk, sizeof(int));
bind(serverId, &serverAddress, sizeof(serverAddress));
listen(serverId, waitQueueSize);
clientId = accept(serverId, &clientAddress, sizeof(clientAddress));
read(clientId, clientBuffer, charsToRead);
nun in sehr einfachen Klassen Extrahieren Funktionalität diesen Code Refactoring wie der Versuch, ich würde (nicht für die Dinge jetzt sehr allgemein zu machen ... YAGNI). Dies ist die Art von Interface Ich denke an:
SocketServer server = SocketServer(parameters);
// SocketServer knows how to create a SocketClient...abstract factories, dependency injection, etc. etc.
SocketClient client = server.accept();
string clientMessage = client.read();
client.write(serverMessage);
Zum Beispiel der SocketServer
Klasse kapselt alle Textvorschlag für einen neuen Socket-Server zu erstellen:
SocketServer server = SocketServer(parameters);
Dann wird, da diese Notwendigkeit zu nennen die System-API, ich muss es nachspionieren:
SocketServer server = SocketServer(systemAPI, parameters);
Nun, was bedeutet es zu testen, dass dieser Code korrekt ist? Es erzeugt keine Ausgabe, die ich überprüfen kann (oder besser, ich mache das alles genau, um die Ausgabe zu kapseln, wie Dateideskriptoren). Ich konnte überprüfen, ob die richtigen Methoden der Mock-API genannt werden, wie:
testSocketCalledWithCorrectParameters() {
systemAPI = mock(SystemAPI).expect(once()).method("socket").with(
SystemAPI.AF_INET,
SystemAPI.SOCK_STREAM,
SystemAPI.PROTO_AUTO
);
ServerSocket(systemAPI, parameters);
}
Ist das eine richtige Situation, wo ich für den Test des Implementierung statt einer Schnittstelle verlassen sollte? Ist man gezwungen, eine Implementierung zu testen, anstatt eine Schnittstelle, die nach schlechtem Design riecht?
Alle anderen Tests, die ich von Satz Erwartungen an die Umsetzung denken konnte:
testServerSocketIsCreatedWithCorrectDescriptor() {
dummyDescriptor = 10;
systemAPI = mock(SystemAPI).when("socket").return(dummyDescriptor);
server = SocketServer(systemAPI, parameters);
assertEquals(dummyDescriptor, server.descriptor);
}
/**
* @expected SocketException
*/
testThrowsExceptionIfErrorCreatingSocket() {
systemAPI = mock(SystemAPI).when("socket").return(SystemAPI.RETURN_ERROR);
SocketServer(systemAPI, parameters);
}
// etc.
Und dann sollte ich schreiben Unit-Tests auch für die socketAPI
, oder sollte ich nur für selbstverständlich, dass es ein sehr sein Klasse "stack wrapper", die nur Aufrufe an die externe API delegiert (und somit nicht getestet werden muss)?
Wenn 'X'' Y' machen soll, wenn 'Z' geliefert wird, wie würdest du es testen? Sie rufen 'X' auf, liefern' Y' und testen das Ergebnis für 'Z'. Wenn Sie nicht können, müssen Sie die grundlegende Infrastruktur schreiben, die Ihnen dies ermöglicht. –
"* Testen einer Implementierung anstelle einer Schnittstelle *" - Was würde es bedeuten, eine Schnittstelle zu testen? –
@OliverCharlesworth Wenn ich eine Funktion 'add (a, b)' habe, kann ich 'add (1,2) == 3' und' add (10,1) == 11' testen, unabhängig davon, wie diese Funktion ist implementiert. – swahnee