Moq: Setting Up Method That Compares Guids Inside A Lambda Expression Fails - c#

This seems like a very simple task but I find it extremely hard to accomplish in Moq. I have a repository that calls a unit of work to query a random picture from a database. This query has one constraint; the random picture from the database cannot be equal to the current picture being displayed. I'm building an NUnit test for the repository and I'd like to mock the unit of work like so:
[TestFixture]
public class When_the_next_random_picture_for_TopSlidePicture_show_has_been_requested
{
private Guid _currentPictureID;
private Picture _randomPicture;
private Mock<IUnitOfWork<Guid>> _unitOfWorkMock;
[SetUp]
public void Context()
{
_currentPictureID = Guid.NewGuid();
_randomPicture = new Picture { ID = Guid.NewGuid() };
_unitOfWorkMock = new Mock<IUnitOfWork<Guid>>();
//TODO: Find out how to setup and verify expression when mocking method with equality comparison in a lambda expression.
_unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(pic => pic.ID != _currentPictureID))
.Returns(_randomPicture);
}
[Test]
public void The_PictureRepository_can_query_next_random_picture()
{
//Arrange
var picRepo = new PictureRepository(_unitOfWorkMock.Object);
//Act
var randomPicture = picRepo.GetNextRandomPicture(_currentPictureID);
//Assert
_unitOfWorkMock.Verify(uow =>
uow.GetRandom<Picture>(pic => pic.ID != _currentPictureID)
, Times.Once());
Assert.AreEqual(_randomPicture, randomPicture);
}
}
In the code above, the GetRandom<Picture>(Expression<Func<Picture, bool>>) in the UnitOfWork is supposed to return any picture in the database who's Guid ID isn't equal to the current pics ID. However, Setup() method called from _unitOfWorkMock returns null regardless of _randomPicture's value. After much research I found the following procedure:
_unitOfWorkMock = new Mock<IUnitOfWork<Guid>>();
_unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(It.IsAny<Expression<Func<Picture, bool>>>()))
.Returns(_randomPicture);
var randomPicture = picRepo.GetNextRandomPicture(_currentPictureID);
//Assert
_unitOfWorkMock.Verify(uow =>
uow.GetRandom<Picture>(It.IsAny<Expression<Func<Picture, bool>>>())
, Times.Once());
This allows the test to pass. BUT, I didn't test whether the picture returned from the db has the same Guid ID of the current picture ID passed in; which is the key principle for even building the test!!!
I love the Moq framework and prefer it over all other testing tools, but this seems like a massive breach of integrity as far as a unit testing platform goes. Please, someone, inform me on what I'm not seeing clearly and show me a simple and easy way to accomplish this seemingly simple task!
Gratitude
UPDATE
Thanks to #StriplingWarrior, I was able to solve the problem! His boolean algebra was wrong, but his answer was sound ;-) I found these modifications to my above code to work:
_unitOfWorkMock = new Mock<IUnitOfWork<Guid>>();
_unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(It.Is<Expression<Func<Picture, bool>>>(e => TestIdMatchExpression(e))))
.Returns(_randomPicture);
private bool TestIdMatchExpression(Expression<Func<Picture, bool>> expr)
{
var func = expr.Compile();
Assert.IsFalse(func(new Picture { ID = _referencePictureID }));
return true;
}
//Assert
_unitOfWorkMock.Verify(uow =>
uow.GetRandom<Picture>(It.Is<Expression<Func<Picture, bool>>>(e => TestIdMatchExpression(e)))
, Times.Once());
Thanks again #StriplingWarrior!

You should be able to use a special overload of It.Is<>() to test the expression:
It.Is<Expression<Func<Picture, bool>>>(e => TestIdMatchExpression(e))
From there you just have to figure out the best way to check the expression that gets passed in. The easiest way is probably to test the behavior: the expression should match a picture with the same guid, and reject a picture with a different one.
bool TestIdMatchExpression(Expression<Func<Picture, bool>> expr)
{
var func = expr.Compile();
Assert.IsTrue(func(new Picture{ID = _currentPictureID}));
Assert.IsFalse(func(new Picture{ID = Guid.NewGuid()}));
}

Remember, when you do unit testing of a method, you have to isolate that test, mock every external dependency including database in your case , do the test of that method for different conditions of the external dependencies
Picture randomPictureExpected = new Picture{ ID=Guid.NewGuid()};
_unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(pic=>pic.ID!=_currentPictureID))
.Returns(randomPictureExpected);
and your assert would be like
var randomPictureActual = picRepo.GetNextRandomPicture(_currentPictureID);
Assert.AreEqual (randomPictureExpected.ID, randomPictureActual.ID);

Related

What is Setup and Returns in MOQ C#?

I read a few tutorial on Moq C# package but I still can't really understand what is Setup and Returns in Moq.
Example,
mock.Setup(p => p.GetEmployeebyId(1)).ReturnsAsync("JK");
Example 2,
mock.Setup(x => x.Save(It.IsAny<DeskBooking>())).Callback<DeskBooking>(
deskBooking =>
{
savedDeskBooking = deskBooking;
});
)
TL;DR: Setup = When, Returns = What
Whenever you write unit tests then you want make sure that a given piece of functionality is working as expected. But most of the time the functionality depends on some other components / environment / external source / whatsoever.
To make your test focused and replayable we need to use test doubles. These will replace your dependencies during the test. We can categorize the test doubles like this:
Dummy: simple code that returns bogus data
Fake: a working alternative which can take shortcuts
Stub: custom logic with predefined data
Mock: custom logic with expectations (interactive stub)
Shim: custom logic at run-time (replace static with a delegate)
Spy: interceptors to record calls
So, whenever you want to create a mock then you have to tell that under what circumstances how should the component behave. In other words when the function is called with a particular input then what should be the expected output.
In case of Moq you can use the Setup to define the when. And the Returns to specify the what.
Here is a simple example. Let's suppose you have the following function:
private IService service;
string MyMethod()
{
int number = service.GetNextNumber();
if(number % 2 == 0)
{
return "even";
}
else
{
return "odd";
}
}
Then you can write the following to test cases:
public void GivenAnEvenNumber_WhenICallMyMethod_ThenItShouldReturnEven
{
//Arrange
var serviceMock = new Mock<IService>();
serviceMock
.Setup(svc => svc.GetNextNumber())
.Returns(2);
...
//Act
var result = SUT.MyMethod();
//Assert
Assert.Equal("even", result);
}
public void GivenAnOddNumber_WhenICallMyMethod_ThenItShouldReturnOdd
{
//Arrange
var serviceMock = new Mock<IService>();
serviceMock
.Setup(svc => svc.GetNextNumber())
.Returns(1);
...
//Act
var result = SUT.MyMethod();
//Assert
Assert.Equal("odd", result);
}
So, as you can see we have used Setup and Returns to direct the control flow in each test case.
Your second example can be considered a Spy, because there you are recording the input for latter assessment.
In example 1
mock.Setup(p => p.GetEmployeebyId(1)).ReturnsAsync("JK");
sets up your mock so when GetEmployeebyId is called with a 1 as the parameter, the mock will return "JK".
In example 2
mock.Setup(x => x.Save(It.IsAny<DeskBooking>())).Callback<DeskBooking>(
deskBooking =>
{
savedDeskBooking = deskBooking;
});
when the Save method is called with any parameter of type DeskBooking, the lambda function will save the parameter in the savedDeskBooking variable. You can then test that you've saved the DeskBooking you expected.

Why C# Xunit Mock returning empty enumeration on IQueryable

trying to mock one method in repository which having return IQueryable.
Please see the unit test method
[Fact]
public void TestMethod()
{
var mockZonal = new Mock<IBaseRepository<ZonalDefinition>>().SetupAllProperties();
var list = new List<ZonalDefinition>() { new ZonalDefinition() { DestinationZone = "401" } }.AsQueryable();
mockZonal.Setup(r => r.GetQueryableFromSql<ZonalDefinition>(new SqlQuerySpec(), new FeedOptions())).Returns(()=>list);
_repoFactory.Setup(r => r.GetGenericRepository<ZonalDefinition>(It.IsAny<string>(), It.IsAny<string>())).Returns(mockZonal.Object);
var afShipmentDetail = new AirFreightShipmentDetail();
var response = _quoteRespository.SetCXShipmentTargetValue(afShipmentDetail);
Assert.NotNull(response);
}
while executing the test am getting the result for mocked method 'GetQueryableFromSql' as 'Enumeration yielded no results'
enter image description here
As far as I understand Moq, you have to setup your method differently:
mockZonal.Setup(r => r.GetQueryableFromSql<ZonalDefinition>(It.IsAny<SqlQuerySpec>(),
It.IsAny<FeedOptions>()))
.Returns(()=>list);
The way you set it up, it would only match if those exact objects were passed to the method (which they won't).
If you need to be more specific with regards to the parameters to match, have a look at the documentation.

Unit Testing Queries that passes Expression<Func<T,bool>> to Repository

I'm having an issue really testing the Querying side of my architecture where I'm calling into a repository that expects an Expression<Func<T, bool>> as parameter for filtering. I was trying to understand this article, where Mark is saying to use Stubs for queries instead.
Lets say I have a query handler:
public class GetUserByEmailQueryHandler : IQueryHandler<GetUserByEmailQuery, User>
{
private readonly IGenericRepository<User> userRepository;
public GetUserByEmailQueryHandler(IGenericRepository<User> userRepository)
{
this.userRepository = userRepository;
}
public User Handle(GetUserByEmailQuery query)
{
return this.userRepository.Find(u => u.Email == query.Email && u.IsLockedOut == false);
}
}
Now my test is going to look something like this:
[Fact]
public void Correctly_Returns_Result()
{
// arrange
var id = Guid.NewGuid();
var email = "test#test.com";
var userRepositoryMock = new Mock<IGenericRepository<User>>();
userRepositoryMock.Setup(
r =>
r.Find(It.IsAny<Expression<Func<User, bool>>>())).Returns(new User { UserId = id }).Verifiable();
// Act
var query = new GetUserByEmailQuery(email);
var queryHandler = new GetUserByEmailQueryHandler(userRepositoryMock.Object);
var item = queryHandler.Handle(query);
// Assert
userRepositoryMock.Verify();
Assert.Equal(id, item.UserId);
}
To me, this test is useless, especially using It.IsAny<Expression<Func<User, bool>>>() as I could be filtering by anything at all. The filter would be a crucial business logic that needs to be tested. How can I test an expression like this? Is this one of those reasons why a generic repository is bad and I should use a specific repository that take exactly the filter parameters that is needed? If that is the case, I'll be moving the expression from one layer to the other and I'd still need to test it
If I should use stubs as Mark said in his blog, are there any examples out there? Am I supposed to run this query on an in-memory list which will be used to validate that the filter expression is correct?
Is this one of those reasons why a generic repository is bad
Yes, it is. Additionally, if you want to follow the SOLID principles of OOD (not that you must, but they are often useful in order to understand the consequences of design decisions), "clients […] own the abstract interfaces" (Agile Principles, Patterns, and Practices, chapter 11). Thus, the interface used by the client should be defined in terms of what the client needs, not by what some general-purpose library exposes.
In this particular case, it looks like what the GetUserByEmailQueryHandler really needs is an ability to query based on an email address, so you could define a reader interface like this:
public interface IUserReader
{
User FindByEmail(string email);
}
This turns GetUserByEmailQueryHandler into something like this:
public class GetUserByEmailQueryHandler : IQueryHandler<GetUserByEmailQuery, User>
{
private readonly IUserReader userRepository;
public GetUserByEmailQueryHandler(IUserReader userRepository)
{
this.userRepository = userRepository;
}
public User Handle(GetUserByEmailQuery query)
{
return this.userRepository.FindByEmail(query.Email);
}
}
At this point, the GetUserByEmailQueryHandler class is so degenerate that you should seriously consider whether it adds any value.
The filter would be a crucial business logic that needs to be tested. How can I test an expression like this?
That really depends on where you want that business logic to execute in the final system. You could test a filter by running it in memory, but if you ultimately plan on executing it on a database server, you'll have to involve the database in your automated tests. That tends to suck, which is the case why most programmers are seriously looking for alternatives to relational databases.
Sorry, but if there's a solution to this particular problem, I don't know what it is.
Personally, I design my system so that they don't rely on complicated filter expressions, but only on simple filter expressions that I can treat as Humble Objects.
To me, this test is useless, especially using
It.IsAny<Expression<Func<User, bool>>>() as I could be filtering by
anything at all. The filter would be a crucial business logic that
needs to be tested. How can I test an expression like this?
No matter what abstraction is used it is needed to test filtering business logic. I answered the similar SO question "Why this mock with Expression is not matching?" a year ago and you can use a code example from it.
In order to test filtering business logic for your design I would change your code the following way:
[Fact]
public void Correctly_Returns_Result()
{
// Arrange
var validEmail = "test#test.com";
var userThatMatches = new User { UserId = Guid.NewGuid(), Email = validEmail, IsLockedOut = false };
var userThatDoesnotMatchByIsLockedOut = new User { UserId = Guid.NewGuid(), Email = validEmail, IsLockedOut = false };
var userThatDoesnotMatchByEmail = new User { UserId = Guid.NewGuid(), Email = "Wrong Email", IsLockedOut = true };
var aCollectionOfUsers = new List<User>
{
userThatMatches,
userThatDoesnotMatchByIsLockedOut,
userThatDoesnotMatchByEmail
};
var userRepositoryMock = new Mock<IGenericRepository<User>>();
userRepositoryMock
.Setup(it => it.Find(It.IsAny<Expression<Func<User, bool>>>()))
.Returns<Expression<Func<User, bool>>>(predicate =>
{
return aCollectionOfUsers.Find(user => predicate.Compile()(user));
});
var sut = new GetUserByEmailQueryHandler(
userRepositoryMock.Object);
// Act
var foundUser = sut.Handle(new GetUserByEmailQuery(validEmail));
// Assert
userRepositoryMock.Verify();
Assert.Equal(userThatMatches.UserId, foundUser.UserId);
}
You can use Return method which allows you to access passed expression and apply it to any target collection of users.

Entity Framework 6 Unit Testing (NSubstitute) - How to test that an object with children does not return children when children are not requested

I have a method to get an Employer using an Entity Framework context (Lazy Loading is disabled). Sometimes I want the Employees included, sometimes I don't so I have the following code in my data access class:
public Employer GetEmployer(int employerId, bool includeRelationships)
{
Employer employer;
if (includeRelationships)
{
employer = (from e in this.context.Employers.Include(e => e.Employees)
where e.EmployerId == employerId
select e).SingleOrDefault();
}
else
{
employer = this.context.Employers.SingleOrDefault(e => e.EmployerId == employerId);
}
return employer;
}
From several questions about how to use NSubstitute to substitute EF context returns I have this extension method in my test project to hook up the DbSet calls for substitution (specifically NSubstitute DbSet / IQueryable<T>):
public static IDbSet<T> Initialise<T>(this IDbSet<T> dbSet, IQueryable<T> data) where T : class
{
dbSet.Provider.Returns(data.Provider);
dbSet.Expression.Returns(data.Expression);
dbSet.ElementType.Returns(data.ElementType);
dbSet.GetEnumerator().Returns(data.GetEnumerator());
return dbSet;
}
This is then used to initialise a substitute set of Employers in the test class:
[TestInitialize]
public void TestInitialise()
{
this.context = Substitute.For<EmployerContext>();
this.dao = new EmployerDao(this.context);
var employers = new List<Employer>();
var employerWithoutEmployee = new Employer { EmployerId = 1 };
employers.Add(employerWithoutEmployee);
var employerWithEmployee = new Employer { EmployerId = 2 };
var employee = new Employee { EmployeeId = 1, EmployerId = 2, Employer = employerWithEmployee };
employerWithEmployee.Employees.Add(employee);
employers.Add(employerWithEmployee);
this.substituteEmployers = Substitute.For<IDbSet<Employer>>().Initialise(employers.AsQueryable());
this.context.Employers.Returns(this.substituteEmployers);
}
So, I now have a test that looks like this:
[TestMethod]
public void ReturnsEmployerWithNullEmployeeWhenIncludeIsFalse()
{
// Assemble
var expectedEmployer = this.substituteEmployers.First(e => e.Employees.Any();
var employerId = expectedEmployer.EmployerId;
// Act
var actualEmployer = this.dao.GetEmployer(employerId, false);
var actualEmployee = actualEmployer.Employees.FirstOrDefault();
// Assert
Assert.AreSame(expectedEmployer, actualEmployer);
Assert.IsNotNull(actualEmployer);
Assert.IsNull(actualEmployee);
this.context.Employers.ReceivedWithAnyArgs();
}
This test is failing on Assert.IsNull(actualEmployee);
In real usage, GetEmployer will return an Employer with no Employee children.
However, because I am substituting an Employer with Employee (because this is what I am testing!) the method is returning the substitute which has an Employee.
How can I test this?
Or, am I testing incorrectly?
Should I instead use the Employer which doesn't have an Employee, because that is what the context would return?
But then doesn't that make the test pointless!?!
I'm thinking myself in circles here...
Many times I have tried to mock out DbContext with different techniques. But every time when I thought "yeah, this time it behaves like real EF!" I have found yet another use-case when mock does not behave like a real thing. An having tests that pass with mocks does give you a false confidence. But when the same actions happen in production, you get exceptions and errors.
So my conclusion was to stop trying to mock DbContext and just do integration tests. It is a bit problematic to set up, but setting up realistic mock takes even more time! And I've written about how to have trouble-free integration tests in my blog: http://tech.trailmax.info/2014/03/how-we-do-database-integration-tests-with-entity-framework-migrations/
Now I tend to write a lot of integration tests (for CRUD stuff) that actually go into DB and mess about. Gives you much more assurance (rather than using db-mock) that the same actions will work in production.
Not really an answer to your question. Just my .02$
This is not possible. It is a limitation of the EF "in-memory" testing model. See this article for details:
https://msdn.microsoft.com/en-us/data/dn314429#limitations

LambdaExpression comparison

I was playing around with testing using machine specifications and there is something that i am just not able to do, was wondering if somebody have been there before,
Is there any way to using Rhino Mocks to create a stub for a method that uses a lambda expression, i found that i can do the following
Having this method in a sample class:
public void UpdateVisit(int userId){
var user = repository.FindBy<User>(x=>x.Id==userId && user.IsActive ==true);
user.Visit = user.Visit + 1;
repository.Save(user);
}
I can stub the method like this:
//...Inside test method
var user = new User();
repository.Stub(x=>x.FindBy<User>(Arg<Expression<Func<User,bool>>>.Is.Anything)).Return(user);
The thing is I would like to stub the method not to Any Lambda Expression, just for the specific lambda expression "x=>x.Id==userId && user.IsActive ==true", so that the test would fail if this expression changes in the method...
I guess i could create a mock repository that does not go to the database and test the behavior in the lambda though this, i was wondering if there is another approach to this...
Appreciate any suggestions on this,
Thanks
You don't want to test that the particular lambda expression is used in the method. You want to test the behavior that the method is suppose to have. Testing implementation details like a specific lambda expression is in general too brittle. Instead:
[Fact]
UpdateVisit_updates_Visit_for_user_that_is_in_the_repository_and_is_active() {
// set up mock repository with dummy user having
// userId == 1,
// IsActive == true,
// Visit = 42
// invoke UpdateVisit
// pull userId == 1 from the repository
Assert.Equal(43, user.Visit);
}
[Fact]
UpdateVisit_does_not_update_visit_for_user_that_is_not_active() {
// etc.
}

Categories

Resources