关于模拟框架C#和单元测试的问题

本文关键字:单元测试 问题 框架 于模拟 模拟 | 更新日期: 2023-09-27 17:58:37

我有一个读取pop3电子邮件服务器的类。我想为包含类编写一些单元测试,所以我需要模拟POP3服务器类。我使用的是OpenPOP.Net。所以我有一个像这样的构造函数:

EmailHost(string email, string password, string pop3Address, int port)
... etc....

然后我有一个连接类:

private void Connect()
{
    _pop3 = new Pop3Client();
    etc...

因此,对Pop客户端的引用被隐藏在类的内部。为了能够模拟它,我需要做一些有趣的事情,因为在Pop3Client上使EmailHost成为泛型,或者添加一些默认函数来完成上面的行:

 public EmailHost<PopClass>(...)

public EmailHost(... params, Func popGenerate = () => new Pop3Client())

因此,我似乎不得不稍微折衷一下我的构造函数,使其与mock一起工作。(很明显,我会定义一个IPop3Client等等。)

你对如何正确地做到这一点有什么想法吗?

编辑:

jOk提供了一个有趣的答案,问题是它不太适合我正在做的事情。在这种特殊情况下,我需要在Pop客户端中处理多个电子邮件地址,并且这些地址是动态添加的。因此,在添加每个电子邮件地址时,您需要创建一个新的Pop3Client。此外,我想隐藏POP3本身的实现,这样他们的用户就不需要尽可能多地了解它。

对此还有其他想法吗?

感谢您的输入btw.

关于模拟框架C#和单元测试的问题

我想你已经接近了。

与其传入最终将用于创建Pop3Client实例的所有参数,不如考虑注入一个Pop3Client实例。

public EmailHost(IPop3Client client) {
}

通过这样做,您将从创建Pop3Client对象的职责中删除EmailHost类。相反,这种责任转移到了其他地方,最常见的是IoC容器。

我无法从您发布的代码中判断Pop3Client是否基于接口。如果是,那就太好了,您可以在测试中模拟/存根它并注入依赖项。如果没有,那么就需要更多的工作来操纵它,以便在这种情况下工作。它可以很简单,只需围绕类编写一个包装器(和相应的接口),就可以公开您在EmailHost中使用的方法。然后可以使用它来代替上面示例中的IPop3Client。

这有道理吗?如果您需要更多指导,请告诉我。

使用类似Castle Windsor的东西来进行服务定位。如果你不想更改构造函数,可以对容器调用Resolve,但这不是正确的方法。将依赖项放在构造函数中是可以的,建议这样做。

我相信Moles会让您在不更改任何代码的情况下覆盖_pop3私有局部变量:

http://research.microsoft.com/en-us/projects/pex/downloads.aspx