我开始了一些原型代码,沿着这些路线云:设计类调用外部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 knows how to create a SocketClient...abstract factories, dependency injection, etc. etc.
SocketClient client = server.accept();
string clientMessage = client.read();
client.write(serverMessage);
例如,SocketServer
类封装了所有样板创建一个新的socket服务器:
SocketServer server = SocketServer(parameters);
然后,因为这需要调用系统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(因此不需要测试)之外,什么也不做?
如果当提供'Z'时'X'应该做'Y',你会如何测试它?您将调用'X',提供'Y'并测试'Z'的结果。如果你不能,你需要编写可以让你这样做的基础设施。 –
“*测试实现而不是接口*” - 测试接口意味着什么? –
@OliverCharlesworth如果我有一个函数'add(a,b)',我可以测试'add(1,2)== 3'和'add(10,1)== 11',无论这个函数如何实现。 – swahnee