如何使用moq验证类似的对象是作为参数传递的?

Byr*_*ahl 22 c# unit-testing moq

我曾经有过几次这样的事情会有所帮助.例如,我有AccountCreator一个Create方法,需要一个NewAccount.我AccountCreator有一个IRepository最终将用于创建帐户.我AccountCreator将首先将属性映射NewAccountAccount,第二次传递Account到repo以最终创建它.我的测试看起来像这样:

public class when_creating_an_account
{
    static Mock<IRepository> _mockedRepository;
    static AccountCreator _accountCreator;
    static NewAccount _newAccount;
    static Account _result;
    static Account _account;

    Establish context = () =>
        {
            _mockedRepository = new Mock<IRepository>();
            _accountCreator = new AccountCreator(_mockedRepository.Object);

            _newAccount = new NewAccount();
            _account = new Account();

            _mockedRepository
                .Setup(x => x.Create(Moq.It.IsAny<Account>()))
                .Returns(_account);
        };

    Because of = () => _result = _accountCreator.Create(_newAccount);

    It should_create_the_account_in_the_repository = () => _result.ShouldEqual(_account);
}
Run Code Online (Sandbox Code Playgroud)

所以,我需要的是替换It.IsAny<Account>,因为这不能帮助我验证是否创建了正确的帐户.令人惊奇的是......

public class when_creating_an_account
{
    static Mock<IRepository> _mockedRepository;
    static AccountCreator _accountCreator;
    static NewAccount _newAccount;
    static Account _result;
    static Account _account;

    Establish context = () =>
        {
            _mockedRepository = new Mock<IRepository>();
            _accountCreator = new AccountCreator(_mockedRepository.Object);

            _newAccount = new NewAccount
                {
                    //full of populated properties
                };
            _account = new Account
                {
                    //matching properties to verify correct mapping
                };

            _mockedRepository
                .Setup(x => x.Create(Moq.It.IsLike<Account>(_account)))
                .Returns(_account);
        };

    Because of = () => _result = _accountCreator.Create(_newAccount);

    It should_create_the_account_in_the_repository = () => _result.ShouldEqual(_account);
}
Run Code Online (Sandbox Code Playgroud)

请注意,我改变了It.IsAny<>It.IsLike<>和人口稠密传递Account对象.理想情况下,在后台,有些东西会比较属性值,如果它们都匹配则让它通过.

那么,它是否已经存在?或者这可能是您以前做过的事情并且不介意共享代码?

Der*_*eer 30

要根据类似标准存根存储库以返回特定值,以下内容应该有效:

_repositoryStub
    .Setup(x => x.Create(
        Moq.It.Is<Account>(a => _maskAccount.ToExpectedObject().Equals(a))))
    .Returns(_account);
Run Code Online (Sandbox Code Playgroud)

  • 如果有人偶然发现了这个答案,并想尝试同样的事情,你必须包含ExpectedObjects库.https://github.com/derekgreer/expectedObjects或`install-package ExpectedObjects` (6认同)

k0s*_*tya 15

以下内容对您有用:

Moq.It.Is<Account>(a=>a.Property1 == _account.Property1)
Run Code Online (Sandbox Code Playgroud)

但是,正如提到的那样,您必须实现匹配条件.

  • 我每天都用它.但想象"a"是一个有50个属性的类.我宁愿能够使用预期的对象模式将实际对象(及其所有属性)与预期对象(具有所有预期属性)进行比较.这就是我要坚持的. (2认同)

yoe*_*alb 8

我已经使用FluentAssertians 库(它更加灵活并且有很多好处)来完成此操作,如下例所示:

_mockedRepository
        .Setup(x => x.Create(Moq.It.Is<Account>(actual =>
                   actual.Should().BeEquivalentTo(_account, 
                       "") != null)))
        .Returns(_account);
Run Code Online (Sandbox Code Playgroud)

请注意空参数,这是必需的,因为这是一个不能使用默认参数的 lambda 表达式。

另请注意!= null表达式,它只是将其转换为bool以便能够编译,并且在相等时能够通过,因为当它不相等时FluentAssertians就会抛出。


请注意,这仅适用于较新版本的,对于较旧版本,您可以执行http://www.craigwardman.com/Blogging/BlogEntry/using-FluentAssertians Fluent-assertions-inside-of-a-moq-verify 中描述的类似方法

它涉及AssertionScope在以下代码中使用 as

public static class FluentVerifier
{
    public static bool VerifyFluentAssertion(Action assertion)
    {
        using (var assertionScope = new AssertionScope())
        {
             assertion();

             return !assertionScope.Discard().Any();
        }
    }
 }
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

_mockedRepository
            .Setup(x => x.Create(Moq.It.Is<Account>(actual => 
                   FluentVerifier.VerifyFluentAssertion(() =>
                       actual.Should().BeEquivalentTo(_account, "")))))))
            .Returns(_account);
Run Code Online (Sandbox Code Playgroud)