私はこれらの線に沿って行くいくつかのプロトタイプのコードで始まっ:外部APIを呼び出すクラスを設計するとき、テストの実装が正しいですか?
// 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);
今私は(今のところ、物事は非常に汎用的にしようとしない非常に単純なクラスに機能を抽出し、このコードをリファクタリングしたいのですが... YAGNI)。このニーズを呼び出すためにあるため、その後
SocketServer server = SocketServer(parameters);
:これは私が考えているインタフェースの一種である:例えば
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);
、SocketServer
クラスは、新しいソケットサーバーを作成するためのすべての定型文をカプセル化システムAPI、私はそれを嘲笑する必要があります:
SocketServer server = SocketServer(systemAPI, parameters);
ここで、このコードが正しいことをテストすることは何を意味していますか?それは私が確認できる出力を生成しません(あるいは、ファイルディスクリプタのように出力をカプセル化するためにこれを行うのがより良い)。私はモックAPIの正しい方法は、同様に、呼ばれていることを確認することができます:
testSocketCalledWithCorrectParameters() {
systemAPI = mock(SystemAPI).expect(once()).method("socket").with(
SystemAPI.AF_INET,
SystemAPI.SOCK_STREAM,
SystemAPI.PROTO_AUTO
);
ServerSocket(systemAPI, parameters);
}
これは私が代わりにインタフェースの実装をテストするに頼る必要があり、適切な状況ですか?悪いデザインのインターフェイスの臭いではなく、実装をテストすることを余儀なくされていますか?
私は実装のセットの期待を考えることができるすべての他のテスト:
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.
そして、私はsocketAPI
のためにも、ユニットテストを書くべきか、私はちょうどそれは非常にになることを当然取るべきダンプラッパークラスで、外部APIへの呼び出しを委任するだけで何もしないので、テストする必要はありません。
'X'が' Z'を提供するときに 'Y'を行うと仮定した場合、どうやってテストしますか? 'X'を呼び出して' Y'を与え、 'Z'の結果をテストします。できない場合は、基本的なインフラストラクチャを作成する必要があります。 –
"*インターフェイスではなく実装をテストする*" - インターフェイスをテストすることはどういう意味ですか? –
@OliverCharlesworthもし 'add(a、b)'関数を持っていれば、この関数がどのように機能しているかにかかわらず、 'add(1,2)== 3'と' add(10,1)== 11'をテストできます。実装されました。 @EugeneSh。 – swahnee