Как использовать moq для проверки того, что аналогичный объект был передан в качестве аргумента?
У меня было несколько случаев, когда что-то вроде этого было бы полезно. Я имею, например, AccountCreator
с Create
методом, который принимает NewAccount
. Мой AccountCreator
имеет IRepository
, который в конечном итоге будет использоваться для создания учетной записи. Мой AccountCreator
сначала отобразит свойства от NewAccount
до Account
, второй передайте 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();
_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
. В идеале, в фоновом режиме, что-то сравнивало бы значения свойств и пропускало бы их, если они все совпадают.
Итак, он уже существует? Или это может быть что-то, что вы делали раньше и не хотели бы делиться кодом?
Ответы
Ответ 1
Чтобы заглушить репозиторий, чтобы вернуть определенное значение, основанное на подобных критериях, должно работать следующее:
_repositoryStub
.Setup(x => x.Create(
Moq.It.Is<Account>(a => _maskAccount.ToExpectedObject().Equals(a))))
.Returns(_account);
Ответ 2
Для вас должно работать следующее:
Moq.It.Is<Account>(a=>a.Property1 == _account.Property1)
Однако, как уже было сказано, вы должны выполнить критерии соответствия.
Ответ 3
Я не смог найти ничего, что точно соответствует тому, что описано в вопросе. В то же время лучший способ найти проверку объектов, переданных в качестве аргументов для издевающихся методов (без роскоши референциального равенства), представляет собой комбинацию Callback
и шаблона ожидаемого объекта для сравнения фактического с ожидаемым объект:
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);
}
Ожидаемый шаблон объекта велик, но его сложно реализовать на С#, поэтому я использую библиотеку, которая обрабатывает все, что для меня. https://github.com/derekgreer/expectedObjects
В моем последнем наблюдении рассматриваются свойства в фактической учетной записи, прошедшей мимо, и сравнивается каждый с одним и тем же свойством на моем "ожидаемом объекте". Таким образом, у меня нет огромного списка проверок свойств, и у меня нет тонких тестовых наблюдений.