c# - Moq - 调用原始方法实现但更改输入参数之一
问题描述
我在一些集成测试中使用 Moq(更新不是我自己的现有测试脚本和代码)并且我正在测试一个 BuinessService,其中注入了一个发送电子邮件的电子邮件接口。
public interface IEmailService
{
void CreateMailItem(string To, string Subject, string Body);
string GetEmailAddress(string staffmember);
}
最初我只是 Moq'd IEmailService接口,它工作得很好,但由于代码的实现方式,我需要调用默认接口实现,即EmailService来测试。我知道我不应该。
我知道我可以像下面这样的方法起订量,但我想做的是让代码调用原始实现EmailService.CreateMailItem 并且只更改单个参数,以便将电子邮件发送到测试帐户而不是真实的真实帐户。
var emailMock = new Mock<EmailService>() { CallBase = true };
emailMock.Setup(x => x.CreateMailItem("test@test.com", It.IsAny<string>(), It.IsAny<string>()));
email = emailMock.Object;
我可以使用 Moq 调用原始的 CreateMailItem 方法,但将“To”参数更改为我的测试电子邮件帐户并保持其他参数不变。?
解决方案
不管你想做什么——你做错了。
如果EmailService
是您要测试的系统,那么您永远不应该模拟它。只需使用适当的参数和结果调用您要测试的方法Assert
。
如果EmailService
是一个依赖项,那么你永远不应该调用实际的实现 - 这会错过模拟某些东西的全部要点,你想将自己与实现断开连接并提供一个模拟方法,该方法将简单地完成系统对它的期望测试。
编辑:
您可以使用 Moq 并以这种方式破解它:
var emailInstance = new EmailService():
var emailMock = new Mock<EmailService>() { CallBase = true };
emailMock.Setup(x => x.CreateMailItem(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Callback((_, arg2, arg3) => emailInstance.CreateMailItem("test@test.com", arg2, arg3));
因此,现在当您emailMock.CreateMailItem
使用任何参数调用您的时,它会将调用重定向到实际实例并与您的测试电子邮件交换第一个参数。
请注意,这样的测试称为集成测试。您实际上是在测试模块如何在一个实时的(尽管是预制的)环境中相互交互。如果您可以强制被测系统使用测试电子邮件而不是使用模拟,这可能会更好,但这应该可以完成工作。
推荐阅读
- django - 如何获取到我的views.py的网页的完整路径?
- python - 如何在执行比较时忽略 Nan
- vue.js - 如何将锚链接添加到页面的各个部分?
- botframework - 如何在 Bot Framework 中获取用户详细信息
- c# - 当字符串值具有“\r\n\r\n”时,如何在c#中基于“\r\n”拆分字符串
- java - 猜数字android应用程序-输入空值后崩溃
- javascript - Flutter Web:使用 flutter build web 构建时缺少 main.dart.js 和 JavaScript 文件,但使用 flutter run 可以正常工作
- javascript - 如何编辑或调用这个 jQuery 函数来处理原生 JavaScript onmouseout?
- json - 在 Zapier 中处理列响应,其中一列为空白
- java - 即使行上没有任何内容为空,空指针异常