Moq - 调用原始方法实现,但更改其中一个输入参数



我正在一些集成测试中使用 Moq(更新不是我自己的现有测试脚本和代码(,并且我正在测试一个注入电子邮件接口以发送电子邮件的 BuinessService。

public interface IEmailService
{
void CreateMailItem(string To, string Subject, string Body);
string GetEmailAddress(string staffmember);
}

最初我只是Moq 的 IEmailService接口并且工作正常,但由于代码的实现方式,我需要调用默认接口实现,即电子邮件服务进行测试。我知道我不应该。

我知道我可以像下面这样修改方法,但我想做的是让代码调用原始实现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时,它会将调用重定向到实际实例,并将第一个参数与您的测试电子邮件交换。

请注意,这样的测试将称为集成测试。您实际上是在测试模块在实时(尽管是预制(环境中如何相互交互。如果您可以强制被测系统使用测试电子邮件而不是使用模拟,可能会更好,但这应该可以完成工作。

我认为您可以模拟该函数并使用对测试函数的回调,该函数更改地址然后调用真正的函数。

不过我还没有尝试过,它可能会陷入无限循环。

emailMock.Setup(x => x.CreateMailItem(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())
.CallBack<string, string, string>(this.TestCreateMailItem));
email = emailMock.Object;
private void TestCreateMailItem(string to, string from, string address)
{
emailMock.Object.CreateMailItem("test@test.com", from, address);
}

最新更新