Moq - 在设置的返回中使用 It.IsAny 时会发生什么? [英] Moq - What happens when using It.IsAny in a setup's return?

查看:76
本文介绍了Moq - 在设置的返回中使用 It.IsAny 时会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am performing unit tests in C# using Moq. One test in particular I have created an interface wrapper over System.Net.Mail.SmtpClient so that it can be mocked.

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.

In my tests of this wrapper, to ensure that the method Send() is called, I have mocked the interface, and in setting up the mock, I'm using the Setup() to assign values to the properties of that object. In all documentation, I see that the .Return() of those setups are returning a specific value of the type that these methods are expecting. However, before I understood it further, I instead used It.IsAny<T> in the returns.

[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 的 Return 中使用 It.IsAny() 会出现什么问题?code>Setup() 还是模拟对象?

What I've noticed is that the tests passed. Since I haven't seen this elsewhere, I understand that this is not best practice. What I'm asking, is why is this not used, and what problems can come up with using It.IsAny<T>() inside the Return of a Moq's Setup() or a mocked object?

推荐答案

It 用于在 Moq 表达式中过滤和匹配参数.

It is meant to be used in Moq expressions for the filtering and matching of arguments.

允许为方法调用中的参数指定匹配条件,而不是特定的参数值.它"指的是被匹配的参数.

Allows the specification of a matching condition for an argument in a method invocation, rather than a specific argument value. "It" refers to the argument being matched.

It.IsAny() 通常在方法调用的实际参数值不相关时使用.当作为 SetupVerify 表达式之外的值传递时,It.IsAny() 传递通用参数的默认值.所以对于引用类型,它会传递 null 等等.

It.IsAny<T>() is typically used when the actual argument value for a method call is not relevant. When passed as a value outside of the Setup or Verify expressions It.IsAny<T>() passes the default value of the generic argument. So for reference types it will pass null and so forth.

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

While in your scenario it does not fail, it is generally advised not to use the It class for anything other than matching arguments passed to mocked dependencies.

在进行测试时,通常使用 Returns 来返回使用值.如果被测对象在调用模拟时期望一个值,而模拟是 Setup 以返回 It.IsAny(),则测试将执行以意想不到的方式.

One typically uses the Returns to return a value of use when exercising a test. If a subject under test is expecting a value when a mock is invoked and instead the mock was Setup to return It.IsAny<T>(), then the test would behave in an unexpected manner.

给出以下简单示例

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

由于It.IsAny<T>()

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

这篇关于Moq - 在设置的返回中使用 It.IsAny 时会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆