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

时间:2018-08-10 07:52:39

标签: c# moq

我在某些集成测试中使用了Moq(更新了不是我自己的现有测试脚本和代码),并且正在测试BuinessService,该服务中已注入电子邮件接口来发送电子邮件。

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

最初,我只是Moq'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”参数更改为我的测试电子邮件帐户,并保持其他参数不变。

2 个答案:

答案 0 :(得分:2)

无论您要做什么,都做错了。

如果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));

现在,当您使用 any 参数调用emailMock.CreateMailItem时,它将把调用重定向到实际实例,并与测试电子邮件交换第一个参数。

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

答案 1 :(得分:1)

我认为您可以模拟该函数并使用一个回调到测试函数,该函数将更改地址,然后调用真实函数。

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

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);
}