在测试该 API 的包装器时,我的单元测试是否应该直接接触该 API



我编写了一些单元测试,用于测试FTP服务器API的包装器

单元测试和 FTP 服务器都在同一台计算机上。

包装器 API 部署到我们的平台,并在远程处理和 Web 服务方案中使用。包装器 API 本质上采用 XML 消息来执行任务,例如添加/删除/更新用户、更改密码、修改权限......那种东西。

在单元测试中,例如要将用户添加到虚拟域,我创建要发送到 API 的 XML 消息。API 完成它的工作并返回一个响应,其中包含有关操作是成功还是失败的状态信息(错误代码、验证失败等)。

为了验证 API 包装器代码是否确实做了正确的事情(如果响应指示成功),我调用 FTP 服务器的 COM API 并直接查询其存储,以查看例如在创建用户帐户时,是否确实创建了用户帐户。

这闻起来难闻吗?

更新1:@Jeremy/Nick:包装器是测试的重点,FTP服务器及其COM API是第三方产品,可能经过良好测试且稳定。包装器 API 必须解析 XML 消息,然后调用 FTP 服务器的 API。我将如何验证,这可能是一个愚蠢的情况,包装器是否正确设置了用户帐户的特定属性。例如,由于包装器代码中的拼写错误,设置了FTP帐户的错误属性或属性。一个很好的例子是设置上传和下载速度限制,这些可能会在包装器代码中被转置。

更新2:感谢大家的回答。对于那些建议使用模拟的人,我已经想到了,但是那里的灯还没有亮起,我仍在努力弄清楚如何让我的包装器与FTP服务器的模拟一起工作。模拟将驻留在哪里,我是否将所述模拟的实例传递给包装器 API 以供使用,而不是调用 COM API?我知道嘲笑,但很难理解它,主要是因为我发现大多数示例和教程都非常抽象,并且(我很惭愧地说)接近于难以理解。

您似乎正在混合单元和组件测试问题。

  • 如果要对包装器进行单元测试,则应使用模拟FTP服务器,并且不涉及实际服务器。好的一面是,您通常可以像这样实现 100% 自动化。
  • 如果您正在对整个事情进行组件测试(包装器 + FTP 服务器协同工作),请尝试在与测试相同的级别验证您的结果,即通过您的包装器 API。例如,如果您发出命令以上传文件,则接下来发出命令以删除/下载该文件以确保文件已正确上传。对于更复杂的操作,其中测试结果并非易事,请考虑诉诸您提到的COM API"后门",或者可能涉及一些手动验证(是否所有测试都需要自动化?

为了验证 API 包装器代码是否确实做了正确的事情(如果响应指示成功),我调用了 FTP 服务器的 COM API

停在那里。 你应该模拟FTP服务器,包装器应该对模拟进行操作。

如果您的测试同时运行包装器和 FTP 服务器,则不是单元测试。

要使用模拟对象测试包装器,您可以执行以下操作:

  • 编写与 FTP 服务器的 COM API 具有相同接口的 COM 对象。这将是您的模拟对象。您应该能够通过依赖注入将两者的接口指针传递给包装器来交换真正的 FTP 服务器和模拟对象。
  • 模拟对象应根据其接口上调用的方法(模仿 FTP 服务器 API)以及使用的参数值实现硬编码行为:
  • 例如,如果您有一个UploadFile方法,则可以盲目返回成功结果,并可能将传入的文件名存储在字符串数组中。
  • 当您遇到包含"错误"的文件名时,您可以模拟上传错误。
  • 当您遇到文件名中带有"慢"时,您可以模拟延迟/超时。
  • 稍后,DownloadFile 方法可以检查内部字符串数组,以查看具有该名称的文件是否已"上传"。

某些测试用例的伪代码是:

//RealServer theRealServer;
//FtpServerIntf ftpServerIntf = theRealServer.getInterface();
// Let's test with our mock instead
MockServer myMockServer;
FtpServerIntf ftpServerIntf = myMockServer.getInterface();
FtpWrapper myWrapper(ftpServerIntf);
FtpResponse resp = myWrapper.uploadFile("Testing123");
assertEquals(FtpResponse::OK, resp);
resp = myWrapper.downloadFile("Testing123");
assertEquals(FtpResponse::OK, resp);
resp = myWrapper.downloadFile("Testing456");
assertEquals(FtpResponse::NOT_FOUND, resp);
resp = myWrapper.downloadFile("SimulateError");
assertEquals(FtpResponse::ERROR, resp);

我希望这有帮助...

我同意 Nick 和 Jeremy 关于不接触 API 的观点。 我会考虑嘲笑 API。


http://en.wikipedia.org/wiki/Mock_object
如果是 .NET,则可以使用:
最小起订量:http://code.google.com/p/moq/

还有一堆其他的嘲笑图书馆。

你在测试包装器或 API 什么。 API 应该按原样工作,所以我认为你不需要测试它。 将您的测试工作集中在包装器上并假装 API 不存在,当我编写一个执行文件访问的类时,我不会在流阅读器中对构建进行单元测试......我专注于我的代码。

我会说在测试时,您的 API 应该像数据库或网络连接一样对待。 不要测试它,它不在你的控制之下。

这听起来不像是在问"我应该测试API吗?"——而是在问"我应该使用API来验证我的包装器是否在做正确的事情吗?"

我说是的。单元测试应断言包装器传递 API 报告的信息。例如,在您给出的示例中,我不知道您将如何避免接触 API。所以我不认为它闻起来很糟糕。

如果高级 API 是只写的,我唯一能想到什么时候潜入较低级别的 API 来验证结果是有意义的。例如,如果您可以使用高级 API 创建用户,那么也应该有一个高级 API 来获取用户帐户。使用它。

其他人建议嘲笑较低级别的API。那很好,如果你能做到的话。如果模拟了较低级别的组件,则检查模拟以确保设置了正确的状态应该没问题。

最新更新