Moq - 在设置返回时使用It.IsAny会发生什么?

时间:2018-04-10 19:56:20

标签: 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; }
    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<T>

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

我注意到测试通过了。由于我在其他地方没有看到这个,我明白这不是最佳做法。我问的是,为什么不使用这个,以及在Moq It.IsAny<T>()的{​​{1}}或模拟对象中使用Return会出现什么问题?

1 个答案:

答案 0 :(得分:3)

class RobProject(tk.Tk): def __init__(self): tk.Tk.__init__(self) 意味着在Moq表达式中用于过滤和匹配参数。

  

允许在方法调用中为参数指定匹配条件,而不是特定的参数值。 &#34;它&#34;是指匹配的参数。

It通常在方法调用的实际参数值不相关时使用。当作为It.IsAny<T>()Setup表达式Verify之外的值传递时,会传递泛型参数的默认值。因此,对于引用类型,它将传递 null 等等。

虽然在您的场景中它没有失败,但通常建议不要将It.IsAny<T>()类用于除了传递给模拟依赖项的匹配参数之外的其他任何内容。

通常使用It在执行测试时返回使用值。如果受测试的主体在调用模拟时期望值而非模拟Returns返回Setup,则测试将以意外的方式运行。

给出以下简单示例

It.IsAny<T>()

由于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; } } 的使用不当,以下测试将因NullReferenceException而失败

It.IsAny<T>()