如何对电子邮件客户端进行单元测试
我现在正在开发桌面电子邮件客户端,我想对我的后端进行单元测试。但是,我看不出有什么方法可以实现这一点。为了使我的代码正常工作,它必须连接到工作的邮件服务器。除非我将单元测试绑定到电子邮件帐户,并确保该帐户与我的测试期望的状态相匹配,否则我不知道如何管理它。
有谁对如何测试此类应用程序有任何想法,它的设计依赖于外部因素?
编辑:
添加一些细节:我正在为我的应用程序开发一个 C++ 更高级别的邮件客户端库,它使用 libEtPan(一个 C 库)来实际处理连接到邮件服务器并与其交互的细节。
I'm working on a desktop email client right now, and I want to unit test my backend. However, I can't see a way to make that work. In order for my code to work, it has to connect to a working mail server. Unless I tie my unit tests to an email account, and make sure that account matches the state my tests expect, I don't see how I can manage this.
Does anyone have any ideas on how to test this sort of application, where it relies on external factors by design?
EDIT:
To add some details: I'm working on a C++ higher level mail client library for my application, which uses libEtPan, a C library, to actually handle the details of connecting to the mail server and interacting with it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我会模拟电子邮件服务器,并配置该模拟对象以适当地接受/拒绝电子邮件(取决于您的测试)。
为了有效地做到这一点,您需要一个与电子邮件服务器通信的接口。为了测试,该实现是一个模拟对象。对于部署,您可以将其替换为直接与邮件服务器对话的实现。
请参阅此 C++ 模拟框架的 SO 问题。
I would mock the email server, and configure that mocked object to accept/reject emails as appropriate (depending on your tests).
To do this effectively, you need an interface to talk to your email server through. For testing, the implementation is a mocked object. For deployment you substitute this with an implementation that talks directly to a mail server.
See this SO question for C++ mocking frameworks.
我将通过测试后端来假设,您指的是实际与电子邮件服务器通信的代码段,并测试您拥有的其余软件模拟这一层。
现在,这可能是也可能不是集成测试,具体取决于您的定义单元。坦率地说,我不在乎你决定如何称呼它,但如果你编写一些快速运行并经常执行的自动化测试,那么它们也可能使用与你的单元测试相同的平台。
我会尝试编写此内容,以便它至少可以通过以下两种方式工作 - 第一种是它连接到您可以根据需要设置和配置的进程本地电子邮件服务器。在 Java 中,我使用 Dumpster 但我确信 C++ 也存在类似的东西。
第二种是连接到至少一个可以编写脚本的本地电子邮件服务器。您可以随意涂抹(因此不是真实的,也不是在开发人员之间共享的),并针对它运行相同的一组测试。原因是 SMTP 服务器的开发人员讨厌所有人,您需要检查您的存根是否与真实的东西一样工作。我认为这相当于每个开发人员一个数据库。
现在,如果您还没有编写自己的 SMTP 客户端,并且只有一个围绕现有第 3 方的 外观 API I 不太可能对此进行“集成测试”,因为假设第 3 方 API 已经受到足够的打击,错误已经消失。我会考虑模拟第 3 方 API 并验证外观是否按预期工作。
1) 也许您可以在 CI 周期内执行此操作,然后在所有开发人员之间共享一组电子邮件服务器,并且本地运行仅使用类似的 C++ 垃圾箱。
I'm going to assume by testing the back end you are referring to the bit of code that actually talks to the Email server and to test the rest of your software you have mocked this layer.
Now this may or may not be integration tests depending on your definition unit. Frankly I don't care what you decide to call it but if you write some automated tests that are quick to run and are executed often then they might as well use the same platform as your unit tests.
I'd try to write this so it can work in at lest the following two ways - The first would be that it connects to an process-local email server that you can set up and configure as you need. In Java I use Dumpster but I'm sure alikes exist for C++.
The second would be to connect to at least one local email server that you can script. One that you can splatter as much as you like (so NOT real or shared between developers¹) and run the same set of tests against that. The reason being that the developers of SMTP servers hate everyone and you will want to check that your stub works the same as a real thing. This I see as the equivalent to One Database Per Developer.
Now if you have not written your own SMTP client and just have a facade around an existing 3rd party API I less likely to "integration test" this on the assumption that the 3rd party API has been battered enough that bugs have already fallen out. I would look at mocking the 3rd party API and validating that the facade works as expected.
1) Maybe you could do this just during the CI cycle, so then share one set of email servers between all developers and the local run just uses a C++ Dumpster alike.
您只需要找到一种方法来用存根替换真实的东西,这完全在您的控制之下。通常,这是通过诸如 Rhino.Mocks 之类的模拟框架来完成的。
顺便说一句:如果您使用“真实”电子邮件帐户,那么它就不再是单元测试,而是集成测试......
You just have to find a way to replace the real thing with a stub, that is fully under your control. Usually, this is done with mocking frameworks like Rhino.Mocks.
Btw.: If you'd use a 'real' email account, then it's not a unit test anymore, but an integration test...
由于您很可能不想测试套接字的使用,因此您可能会考虑用不涉及任何 TCP 通信的虚拟服务器实现替换这部分代码。只需对来自客户端的预期请求进行硬编码,然后让虚拟服务器做出适当的响应即可。
As you most likely don't want to test you use of sockets, you might think about replacing that part of your code with a dummy server implementation that doesn't involve any TCP communication. Just hardcode the expected requests from your client and let your dummy server respond appropriately.
安德鲁关于模拟邮件 API 的说法是正确的。您在 C 语言中遇到的问题可以通过以下两种方式之一解决。
有一本很棒的书讲述了如何在困难的情况下进行单元测试:“有效地处理遗留代码”,我极力推荐这本书。不要被标题吓倒,本书将遗留代码视为任何没有单元测试的代码。
Andrew is correct about Mocking the mail API. Your problem with this being in C can be addressed in one of two ways.
There is a great book that addresses how to unit test in difficult situations: "Working Effectively with Legacy Code", I cannot recommend this book highly enough. Don't be put off by the title, the book regards legacy code as any code without unit tests.