I have had a few occasions where something like this would be helpful. I have, for instance, an AccountCreator
with a Create
method that takes a NewAccount
. My AccountCreator
has an IRepository
that will eventually be used to create the account. My AccountCreator
will first map the properties from NewAccount
to Account
, second pass the Account
to the repo to finally create it. My tests look something like this:
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);
}
So, what I need is something to replace It.IsAny<Account>
, because that doesn't help me verify that the correct Account was created. What would be amazing is something like...
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);
}
Notice I changed It.IsAny<>
to It.IsLike<>
and passed in a populated Account
object. Ideally, in the background, something would compare the property values and let it pass if they all match.
So, does it exist already? Or might this be something you have done before and wouldn't mind sharing the code?
Verifiable is to enlist a Setup into a set of "deferred Verify(...) calls" which can then be triggered via mock. Verify() .
Moq provides a library that makes it simple to set up, test, and verify mocks. We can start by creating an instance of the class we're testing, along with a mock of an interface we want to use.
The Moq framework is an open source unit testing framework that works very well with .
To stub out a repository to return a particular value based on like criteria, the following should work:
_repositoryStub
.Setup(x => x.Create(
Moq.It.Is<Account>(a => _maskAccount.ToExpectedObject().Equals(a))))
.Returns(_account);
The following should work for you:
Moq.It.Is<Account>(a=>a.Property1 == _account.Property1)
However as it was mentioned you have to implement matching criteria.
I have done that using the FluentAssertians library (which is much more flexible and has lot's of goodies), as in the following example:
_mockedRepository
.Setup(x => x.Create(Moq.It.Is<Account>(actual =>
actual.Should().BeEquivalentTo(_account,
"") != null)))
.Returns(_account);
Note the empty argument, which is needed since this is a lambda expression which can't use default parameters.
Also note the != null
expression which is just to convert it to bool
so to be able to compile, and to be able to pass when it is equal, since when it is not equal then FluentAssertians
will throw.
Note that this only works in newer versions of FluentAssertians
, for older versions you can do a similar method described in http://www.craigwardman.com/Blogging/BlogEntry/using-fluent-assertions-inside-of-a-moq-verify
It involves using an AssertionScope
as in the following code
public static class FluentVerifier
{
public static bool VerifyFluentAssertion(Action assertion)
{
using (var assertionScope = new AssertionScope())
{
assertion();
return !assertionScope.Discard().Any();
}
}
}
And then you can do:
_mockedRepository
.Setup(x => x.Create(Moq.It.Is<Account>(actual =>
FluentVerifier.VerifyFluentAssertion(() =>
actual.Should().BeEquivalentTo(_account, "")))))))
.Returns(_account);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With