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

C# Moq-调用原始方法实现,但更改其中一个输入参数,c#,moq,C#,Moq,我在一些集成测试中使用Moq(更新一个不是我自己的现有测试脚本和代码),并且我正在测试一个BuinessService,它有一个电子邮件接口,可以发送电子邮件 public interface IEmailService { void CreateMailItem(string To, string Subject, string Body); string GetEmailAddress(string staffmember); } 最初,我只是对IEmailService接

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

public interface IEmailService
{
    void CreateMailItem(string To, string Subject, string Body);
    string GetEmailAddress(string staffmember);
}
最初,我只是对IEmailService接口进行了修改,效果很好,但由于代码的实现方式,我需要调用默认接口实现,即EmailService进行测试。我知道我不应该

我知道我可以使用下面的方法,但我想做的是让代码调用原始实现EmailService.CreateMailItem,只更改单个参数,以便将电子邮件发送到测试帐户,而不是真正的live帐户

var emailMock = new Mock<EmailService>() { CallBase = true };
emailMock.Setup(x => x.CreateMailItem("test@test.com", It.IsAny<string>(), It.IsAny<string>()));
email = emailMock.Object;
var emailMock=new Mock(){CallBase=true};
emailMock.Setup(x=>x.CreateMailItem(“test@test.com“,It.IsAny(),It.IsAny());
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));
var-emailInstance=new-EmailService():
var emailMock=new Mock(){CallBase=true};
emailMock.Setup(x=>x.CreateMailItem(It.IsAny(),It.IsAny(),It.IsAny())
.Callback((_,arg2,arg3)=>emailInstance.CreateMailItem(“test@test.com“,arg2,arg3”);
因此,当您使用任何参数调用
emailMock.CreateMailItem
时,它会将调用重定向到实际实例,并将第一个参数与测试电子邮件交换


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

无论您想做什么,您都做错了

如果您尝试测试的系统是
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));
var-emailInstance=new-EmailService():
var emailMock=new Mock(){CallBase=true};
emailMock.Setup(x=>x.CreateMailItem(It.IsAny(),It.IsAny(),It.IsAny())
.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);
}
emailMock.Setup(x=>x.CreateMailItem(It.IsAny()、It.IsAny()、It.IsAny())
.CallBack(this.TestCreateMailItem));
email=emailMock.Object;
私有void TestCreateMailItem(字符串收件人、字符串发件人、字符串地址)
{
emailMock.Object.CreateMailItem(“test@test.com“、发件人、地址);
}

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

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

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);
}
emailMock.Setup(x=>x.CreateMailItem(It.IsAny()、It.IsAny()、It.IsAny())
.CallBack(this.TestCreateMailItem));
email=emailMock.Object;
私有void TestCreateMailItem(字符串收件人、字符串发件人、字符串地址)
{
emailMock.Object.CreateMailItem(“test@test.com“、发件人、地址);
}

您的目标不明确。你的系统在测试什么?您是否可以向我们展示整个单元测试的概要?您是在测试具体的
EmailService
,还是使用
IEmailService
?如果是后者,为什么要使用
IEmailService
的具体实现?看看这篇文章我更新了我的帖子以回应你的提问。我希望有帮助。你的目标还不清楚。你的系统在测试什么?您是否可以向我们展示整个单元测试的概要?您是在测试具体的
EmailService
,还是使用
IEmailService
?如果是后者,为什么要使用
IEmailService
的具体实现?看看这篇文章我更新了我的帖子以回应你的提问。我希望这会有帮助。我同意你的观察和建议