C# Moq-在设置中使用它时会发生什么。iAny';她回来了吗?

C# Moq-在设置中使用它时会发生什么。iAny';她回来了吗?,c#,unit-testing,moq,C#,Unit Testing,Moq,我使用Moq在C#中执行单元测试。特别是在一个测试中,我在System.Net.Mail.SmtpClient上创建了一个接口包装器,以便对其进行模拟 public class SmtpClient : ISmtpClient { public string Host { get; set; } public int Port { get; set; } public ICredentialsByHost Credentials { get; set; } pub

我使用Moq在C#中执行单元测试。特别是在一个测试中,我在
System.Net.Mail.SmtpClient
上创建了一个接口包装器,以便对其进行模拟

public class SmtpClient : ISmtpClient
{
    public string Host { get; set; }
    public int Port { get; set; }
    public ICredentialsByHost Credentials { get; set; }
    public bool EnableSsl { get; set; }

    public void Send(MailMessage mail)
    {
        var smtpClient = new System.Net.Mail.SmtpClient
        {
            Host = Host,
            Port = Port,
            Credentials = Credentials,
            EnableSsl = EnableSsl
        };

        smtpClient.Send(mail);
    }
}
在我对这个包装器的测试中,为了确保调用方法
Send()
,我模拟了接口,在设置模拟时,我使用
Setup()
为该对象的属性赋值。在所有文档中,我看到这些设置的
.Return()
正在返回这些方法所期望的特定类型的值。然而,在我进一步理解它之前,我在返回中使用了
it.IsAny

[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
{
    _smtpClientMock = new Mock<ISmtpClient>(MockBehavior.Strict);
    _smtpClientMock.Setup(x => x.Port).Returns(8080);
    _smtpClientMock.Setup(x => x.EnableSsl).Returns(false);
    _smtpClientMock.Setup(x => x.Host).Returns("host");
    _smtpClientMock.Setup(x => x.Credentials).Returns(It.IsAny<NetworkCredential>());

    _smtpClientMock.Setup(mockSend => mockSend.Send(It.IsAny<MailMessage>()));
}

[TestMethod]
public void WithValidMailMessageObject_WhenSendIsCalled_EmailClientCallsSmptClientToSendEmail()
{
    //Arrange

    //Act
    _smtpClientMock.Object.Send(new MailMessage());
    //Assert
    _smtpClientMock.Verify(checkMethodIsCalled => checkMethodIsCalled.Send(It.IsAny<MailMessage>()), Times.Once);
}
[分类初始化]
公共静态void ClassInitialize(TestContext TestContext)
{
_smtpClientMock=新模拟(MockBehavior.Strict);
_smtpClientMock.Setup(x=>x.Port).Returns(8080);
_smtpClientMock.Setup(x=>x.EnableSsl).Returns(false);
_smtpClientMock.Setup(x=>x.Host).返回(“主机”);
_smtpClientMock.Setup(x=>x.Credentials).Returns(It.IsAny());
_smtpClientMock.Setup(mockSend=>mockSend.Send(It.IsAny());
}
[测试方法]
public void with validmailmessageobject_when ndiscaled_EmailClientCallsSmptClientToSendEmail()
{
//安排
//表演
_smtpClientMock.Object.Send(newmailmessage());
//断言
_验证(checkMethodIsCalled=>checkMethodIsCalled.Send(It.IsAny()),Times.Once);
}

我注意到考试通过了。因为我没有在其他地方看到过,我知道这不是最佳实践。我想问的是,为什么不使用它,以及使用它会出现什么问题。在Moq的
Setup()
或模拟对象的
Return
中,IsAny()用于在Moq表达式中过滤和匹配参数

允许为方法调用中的参数指定匹配条件,而不是指定特定的参数值。“It”指的是匹配的参数

It.IsAny()
通常在方法调用的实际参数值不相关时使用。当作为
设置
验证
表达式
之外的值传递时,IsAny()将传递泛型参数的默认值。因此,对于引用类型,它将传递null,以此类推

虽然在您的场景中,它不会失败,但通常建议不要将
it
类用于传递给模拟依赖项的匹配参数以外的任何内容

执行测试时,通常使用
返回
返回使用值。如果在调用模拟时被测试的主体期望一个值,而模拟是
Setup
返回
It.IsAny()
,那么测试将以意外的方式进行

下面给出一个简单的例子

public interface IDependency {
    string SomeMethod();
}

public MyClass {
    public bool MyMethod(IDependency input) {            
        var value = input.SomeMethod();

        var result = "Output" + value.ToUpper(); //<-- value should not be null

        return result != null;
    }
}

它用于moq表达式中过滤参数。当作为设置或验证表达式之外的值传递时,它将传递泛型参数的默认值。因此,对于引用类型,它将传递一个事实,即调用了send方法,但这并不意味着您发送电子邮件的代码实际上正在工作。你花了太多的时间去担心一些几乎无关紧要的事情。单元测试功能,测试调用的方法没有那么重要。从技术上来说,该测试只是测试模拟框架是否按预期运行。如果每个人都能理解,根据我的问题,实际测试和正在测试的内容是不相关的。考虑到网上没有找到其他示例,我将最简单的测试放在一起,以演示“It.IsAny()”在返回中的用法。从这个测试中唯一可以得到的是,在返回中使用IsAny不会使测试失败。在这个场景中,它不会使测试失败。这是您所展示内容的唯一优点,在Returns()中有一种将参数从SomeMethod()传递到SomeOtherMethod()的方法。类似的东西:mock.Setup(=>\u0.SomeMethod(It.IsAny(),It.IsAny()).Returns(SomeOtherMethod(It.IsAny(),It.IsAny()));
[TestMethod]
public void MyMethod_Should_Return_True() {
    //Arrange
    var mock = new Mock<IDependency>();
    mock.Setup(_ => _.SomeMethod()).Returns(It.IsAny<string>());
    var subject = new MyClass();
    var expected = true;

    //Act
    var actual = subject.MyMethod(mock.Object);

    //Assert
    Assert.AreEqual(expected, actual);
}