2008-10-17 49 views
8

我写了一些单元测试围绕FTP服务器API测试一个包装。我的单元测试应该在测试该API的包装时直接触摸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:感谢所有的答案。对于那些建议使用mock的人来说,它已经超出了我的想法,但是灯光还没有开启,我仍然在努力让自己的头脑变得如何让我的包装与FTP服务器的模拟一起工作。 mock将驻留在哪里,并且将所述mock的一个实例传递给包装API以使用而不是调用COM API?我意识到嘲笑,但努力让自己头脑发热,主要是因为我发现大多数示例和教程都非常抽象,而且(我很惭愧地说)接近不可理解。

回答

7

你似乎是混合单元&组件测试问题。

  • 如果你是单元测试你的包装,你应该使用模拟FTP服务器,而不涉及实际的服务器。好的一面是,你通常可以实现100%的自动化。
  • 如果您对组件进行组件测试(包装器+ FTP服务器一起工作),请尝试在与测试相同的级别验证结果,即通过包装器API进行验证。例如,如果您发出上传文件的命令,请发出命令删除/下载该文件,以确保文件已正确上传。对于测试结果并不重要的更复杂的操作,请考虑使用您提到的COM API“后门”,或者可能涉及一些手动验证(您的所有测试是否需要自动化?)。
+1

已经研磨过的这种过度的年龄我现在终于明白,当我的单元测试,组件测试或集成测试以及它们的真正含义。 – Kev 2010-03-22 03:45:57

0

你在测试什么包装或API。 API应该按原样工作,所以你不需要测试它,我会想。把你的测试工作集中在包装上,并假装API不存在,当我编写一个文件访问类时,我不会单元测试streamreader中的构建......我专注于我的代码。

0

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

0

这听起来不像你问“我应该测试的API?” - 你问:“我应该使用API​​来验证我的包装是否做得对吗?”

我说是的。你的单元测试应该声明你的包装器传递了API报告的信息。例如,您举例说,我不知道如何避免接触API。所以我不认为它味道不好。

3

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

停在那儿。你应该嘲笑FTP服务器,包装应该对付模拟。

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

0

我唯一能想到的是,如果更高级别的API是只写的,那么在低级别API中验证结果是否合理。例如,如果您可以使用高级API创建用户,那么应该有一个高级API来获取用户帐户。使用它。

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

3

要使用模拟对象测试你的包装,你可以做到以下几点:

  • 编写具有相同的接口作为FTP服务器的COM API的COM对象。这将是你的模拟对象。你应该能够通过依赖注入方式将接口指针传递给包装器来交换真实的FTP服务器和你的模拟对象。
  • 你模仿的对象应该基于一种称为其接口(模仿FTP服务器API)的方法来实现硬编码的行为,并根据所使用的参数值:
  • 举例来说,如果你有一个UploadFile方法,你可以一味地返回一个成功的结果,并可能将传入的文件名存储在一个字符串数组中。
  • 当你遇到一个带有“错误”的文件名时,你可以模拟上传错误。
  • 当您遇到文件名“slow”时,您可以模拟延迟/超时。
  • 稍后,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); 

我希望这有助于...

+1

真的很棒的回答!这基本上只是解释了我试图用单元测试和模拟对象来解决问题的一大堆事情。耻辱我不能给你超过一个upvote! – 2011-08-10 12:57:36