【问题标题】:Question regarding mocking framework C# and unit tests关于模拟框架 C# 和单元测试的问题
【发布时间】:2011-06-09 03:40:35
【问题描述】:

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

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

然后我有一个连接类:

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

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

 public EmailHost<PopClass>(...)

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

所以看来我必须稍微妥协我的构造函数才能使其与模拟一起使用。 (显然我会定义一个 IPop3Client 等等。)

关于如何正确执行此操作的任何想法?

编辑:

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

对此还有其他想法吗?

谢谢你输入btw。

【问题讨论】:

  • 您在项目中使用 Spring 吗?

标签: c# unit-testing mocking


【解决方案1】:

我认为你很接近。

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

public EmailHost(IPop3Client client) {

}

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

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

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

【讨论】:

  • +1 好答案-正如您所说,使依赖项可注入是关键,这是否通过 IOC 容器完成是一个单独的考虑因素-人们似乎经常认为 DI 和使用一个 IOC 容器的隐式链接
  • @Adam Ralph 同意。感谢您强调这一点。
  • 感谢您的信息。我编辑了原件以反映为什么我认为这行不通。
【解决方案2】:

使用诸如温莎城堡之类的东西来做服务定位。如果您不想更改构造函数,请在容器上调用 Resolve ,但这不是正确的方法。将依赖项放在构造函数中很好,建议。

【讨论】:

    【解决方案3】:

    我相信 Moles 会让你覆盖 _pop3 私有局部变量而无需任何代码更改:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 2010-09-10
      • 2011-04-11
      相关资源
      最近更新 更多