设置 Mock 以重定向到重载方法

Setup Mock to redirect to overloaded method

我有一个方法叫做:

SendMail(string from, string to, string subject, string smtpServer)

和一个重载的方法

SendMail(string from, string to, string subject, SmtpClient smtpClient)

在我的单元测试中,我想设置我的 MailService 模拟,以便在调用方法 SendMail(string, string, string, string) 时,我想改为调用重载方法 SendMail(string, string, string, SmtpClient) 并修改最后一个参数到创建的 SmtpClient 测试对象。

有办法吗?

最简单的

mailServiceMock.Setup(m => m.SendMail(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<SmtpClient>()));

如果你愿意,可以装上 callback/return。

您想要的是在您的设置中使用 .Callback(...)

mailServiceMock
  .Setup(m => m.SendMail(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())
  .CallBack((string from, string to, string subject, string server) => mailService.SendMail(from, to, subject, server, SomeSMTPServer)

更重要的是你为什么要这样做?

通常你只会测试你的 mock 是否被调用了 (string, stirng, string, string)。

然后另一个 TestClass/Fixture 你会在调用

时测试它
(string from, string to, string subject, string smtpServer) 

重载,您实际上调用了 SmtpServer 重载并提供了正确的细节。

编辑:评论后

mailService 不是错字。

这将是:

  1. 如果 var mailServiceMock = new Mock<ParentClassNotInterface>{ CallsBase = true } 相同的模拟实例(例如 mailServiceMock.Object)。这当然意味着您的方法 必须 是虚拟的。
  2. class/interface 的实际具体实现。

关于第二个音符,如果我是你,我会将其分解为以下 one/some/all 个:

  • 调用 class/method 调用 SendServer(string, string, string, string) 的单元测试。我会使用我在博客上描述的技术:CodePerf[dot]NET - TDD – Mock.Throw Interface Call Verification Technique

  • 单元测试,当您调用 SendServer(string, string, string, string) 时,它调用 SendServer(string, string, string, SmtpServer) 并且 SmtpServer 设置正确。

  • SendServer(string, string, string, SmtpServer)` 实际发送电子邮件的集成测试。

  • 可能是端到端测试(没有模拟)这一切都有效。