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

问题描述 投票:26回答:4

我有几次遇到类似的情况,这样的事情会很有用。例如,我有一个 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);
}

所以,我需要的是一些东西来代替 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);
}

注意,我改变了 It.IsAny<>It.IsLike<> 并以一个填充的 Account 对象。理想情况下,在后台,有些东西会比较这些属性值,如果它们都匹配,就让它通过。

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

c# unit-testing moq
4个回答
35
投票

要支管一个存储库,根据相似的标准返回一个特定的值,下面的方法应该可以。

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

18
投票

下面的内容应该对你有用

Moq.It.Is<Account>(a=>a.Property1 == _account.Property1)

然而,正如前面提到的,你必须实现匹配标准。


0
投票

我无法找到任何与问题中描述的完全相同的东西。同时,我能找到的最好的方法是将以下方法结合起来,来处理作为参数传递给被嘲讽方法的对象的验证(没有奢侈的引用平等)。Callback 和 Expected Object 模式来比较实际对象和预期对象。

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

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

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

            _mockedRepository
                .Setup(x => x.Create(Moq.It.IsAny<Account>(_account)))
                //here, we capture the actual account passed in.
                .Callback<Account>(x=> _actualAccount = x) 
                .Returns(_account);
        };

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

    It should_create_the_account_in_the_repository = 
        () => _result.ShouldEqual(_account);

    It should_create_the_expected_account = 
        () => _expectedAccount.ToExpectedObject().ShouldEqual(_actualAccount);
}

预期对象模式很好,但在C#中实现起来很复杂,所以我使用了一个库来处理所有的事情。https:/github.comderekgreerexpectedObjects)。

我的最后一个观察值查看实际账户中传递进来的属性,并将每个属性与我的 "预期对象 "上的相同属性进行比较。这样我就没有一个庞大的模拟属性检查列表,也没有大量的测试观察。


0
投票

如果我使用 JSONConvert.SerializeObject 将预期的和实际的对象隐蔽为JSON字符串,然后做一个 equals 之间,它似乎产生了一个可接受的结果。我的想法是,如果对象的字符串表示方式匹配,那么它们的公共属性很可能也是相同的。

© www.soinside.com 2019 - 2024. All rights reserved.