如何对电子邮件客户端进行单元测试

4
我现在正在开发一个桌面邮件客户端,并且想对我的后端进行单元测试。然而,我无法找到一种方法来实现这个目标。为了让我的代码正常工作,必须连接到一个可用的邮件服务器。除非我将我的单元测试与一个电子邮件帐户绑定,并确保该帐户与我的测试所期望的状态匹配,否则我不知道该如何管理这个问题。
有没有人有任何关于如何测试这种依赖外部因素的应用程序的想法?
编辑:
添加一些详细信息:我正在为我的应用程序开发一个C++高级邮件客户端库,它使用libEtPan(一个C库)来处理连接到邮件服务器并与之交互的详细信息。
5个回答

7
我会模拟电子邮件服务器,并配置该模拟对象以根据测试需要接受/拒绝电子邮件。
为了有效地进行此操作,您需要通过接口与电子邮件服务器进行通信。在测试中,实现是一个模拟对象。在部署中,您将其替换为直接与邮件服务器通信的实现。
请参阅此SO问题以获取C ++模拟框架。

问题在于我的后端是一个C库,所以我无法利用模拟它,除非我忽略了什么。 - Matt Moriarity
快速谷歌搜索指向这个网址:http://www.lastcraft.com/cgreen.php 它提供了模拟函数的选项。 - Michael Lloyd Lee mlk
不要忘记,您可以定义一个新接口,将其委托给您的库或提供模拟响应。只需在新接口后隐藏您的库即可(如果原始库接口很大,则可能会有些麻烦,我承认)。 - Brian Agnew
您可以通过链接第二个实现来模拟C API。但是您不能在同一个可执行文件中同时使用模拟和真实的实现。 - iain

2
我翻译如下:

我会假设通过测试后端,您指的是实际与电子邮件服务器通信的代码部分,并且为了测试软件的其余部分,您已经模拟了这个层次。

现在这可能或可能不是集成测试,具体取决于您对单元的定义。老实说,我不关心您决定称其为什么,但如果您编写一些自动化测试,这些测试运行快速且经常执行,那么它们可能与您的单元测试使用相同的平台。

我会尝试将此翻译为至少以下两种方式之一:第一种是连接到一个本地进程的电子邮件服务器,您可以根据需要设置和配置。在Java中,我使用Dumpster,但我相信C++也有类似的东西。第二种是连接至少一个本地可编写脚本的电子邮件服务器。您可以随意操作(因此不是真实或共享的¹),并对其运行相同的测试集。原因是SMTP服务器的开发人员讨厌每个人,您将要检查您的存根与真实事物是否相同。我认为这相当于每个开发者一个数据库
现在,如果您没有编写自己的SMTP客户端,只是围绕现有的第三方API提供了一个外观,我不太可能“集成测试”这一点,因为我假设第三方API已经被破坏了足够多的错误已经出现。我会查看模拟第三方API并验证外观按预期工作。
也许你可以只在CI周期内这样做,然后所有开发人员共享一组电子邮件服务器,本地运行只使用类似于C++垃圾箱的工具。

你知道一种模拟C API的方法吗?我遇到的问题是:如果这是一个C++库,那么看起来很简单。另一个考虑因素是,我不确定我应该从第三方API中得到什么返回,因为这对我来说很新奇,所以我更倾向于设置一个测试邮件服务器而不是模拟API的结果。 - Matt Moriarity
我在发布上述内容后才看到这个要求。我并不经常进行C/C++开发,但http://www.lastcraft.com/cgreen.php看起来很有前途。另一个选择是创建一个薄包装器(基本上是一个可模拟的接口,声明了每个方法,然后是一个真正的调用,只是委托)。 - Michael Lloyd Lee mlk
但如果模拟C API完全不可行,那么请使用类似Dumpster的工具来stub SMTP服务器(如上所述)。 - Michael Lloyd Lee mlk

1

你只需要找到一种方法,用一个完全受你控制的存根来替换真实的东西。通常,这是通过模拟框架(如Rhino.Mocks)来完成的。

顺便说一下:如果你使用一个“真正”的电子邮件账户,那么这就不再是一个单元测试,而是一个集成测试了...


0

关于模拟邮件API,Andrew是正确的。你在使用C语言时遇到的问题可以通过以下两种方式解决:

  • 提供一个简单的C++包装器来进行模拟。
  • 使用链接器提供测试/模拟版本的C API,你必须使用与库提供的相同的头文件,但是你的单元测试将链接到你的模拟C函数而不是库。

有一本很好的书介绍了如何在困难情况下进行单元测试:"Working Effectively with Legacy Code",我非常推荐这本书。不要被标题吓到,这本书认为没有单元测试的任何代码都是遗留代码。


0

由于您很可能不想测试套接字的使用,因此您可以考虑用一个虚拟服务器实现替换代码中涉及任何TCP通信的部分。只需硬编码客户端的预期请求,让您的虚拟服务器做出适当的响应即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接