How can an IRepository be unit tested? - c#

I have written the following method using the Repository mentioned
in the following blog-post (http://www.codecapers.com/post/Using-RavenDB-with-ASPNET-MVC.aspx) using RavenDB:
public User GetUserById(string id)
{
var user = (from usr in _repository.All<User>() where usr.Id == id select usr).FirstOrDefault();
if (user == null)
{
throw new NullReferenceException("No user with the id (" + id + ") could be found.");
}
return user;
}
How would you unit test this method with nunit (and perhaps moq)?
"user" is just a normal class.

Usualy you don't write tests directly against the repository layer.
Say for example you are using nHibernate or Entity Framework, than wirting tests against the repository would technically be testing that framework.
The creators or those ORMs already done that.
Also talking to a database makes your test an integration test not a unit test.
Your unit test would be for example against the business layer mocking out the repository layer.
If you want to write an integration test you also write that against the business layer but don't mock the repository layer and let it go through.

I would do the following to prepare your code:
Make sure your _repository is being passed in through a constructor or property, so that it can be easily changed for tests.
Make sure your _repository variable is declared as the IRepository type, rather than the concrete type.
Then, in your tests:
Create a mock of your interface and pass this in to be your _repository.
Override the .All<User>() method to return a known, hardcoded list of User with suitable values for your tests.
Assert in one test that the correct value is returned when you query an existing ID.
Assert in a separate test that the exception is thrown when you query a non-existant ID.

The first question is going to be - what are you testing in this context? The method provided really only has two outcomes, so you're basically testing whether user is null or not. Is that a value added test?
As for the how, Im assuming _repository is injected via some mechanism? If so, then you simply provide a Mock<IRepository> (insert your type name as appropriate) and inject that in the place of _repository wherever that is injected. Then you can setup the return values and test your method for the exception or not.
mockRepository.Setup(x => x.All<User>()).Returns(new List<User> { ... });

RavenDB is specifically designed so that you don't need to mock everything for unit testing.
Just run it in-memory and you can then perform you unit tests against it directly. See this blog post for more info.
It lets you write code like this:
[Fact]
public void CanQueryForDistinctItemsUsingLinq()
{
using (var store = NewDocumentStore())
{
using (var s = store.OpenSession())
{
s.Store(new { Name = "ayende" });
s.Store(new { Name = "ayende" });
s.Store(new { Name = "rahien" });
s.SaveChanges();
}
store.DocumentDatabase.PutIndex("test", new IndexDefinition
{
Map = "from doc in docs select new { doc.Name }",
Stores = { { "Name", FieldStorage.Yes } }
});
using (var s = store.OpenSession())
{
var objects = s.Query<User>("test")
.Customize(x => x.WaitForNonStaleResults())
.Select(o => new {o.Name })
.Distinct()
.ToList();
Assert.Equal(2, objects.Count);
Assert.Equal("ayende", objects[0].Name);
Assert.Equal("rahien", objects[1].Name);
}
}
}
This comes from RavenDB unit/integration tests, so you'll need some infasctucture to get it working, but it gives the general idea.

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.

Passing value in Mock Rhino test

I have following code:
if (ActiveApplication.GetField("previous_date").Value != ActiveApplication.GetField("new_date").Value)
{
//do something..
}
I want to unit test this. Being new to Rhino tests, I am trying to figure out how to pass value so that i go in the loop. Here is what i have tried:
var previous_date = MockRepository.GenerateMock<IField>();
stubApplication.Stub(x => x.GetField("previous_date")).Return(previous_date);
previous_date.Stub(x => x.GetInternalValue()).Return("20160525");
var new_date = MockRepository.GenerateMock<IField>();
stubApplication.Stub(x => x.GetField("new_date")).Return(new_date);
new_date.Stub(x => x.GetInternalValue()).Return("20160525");
Can someone please tell me what am i doing wrong?
This returns previous_date, an interface of type IField:
stubApplication.Stub(x => x.GetField("previous_date")).Return(previous_date)
Because it's not a base class implementation, your code uses the Value property on the interface which has to be setup in a mock as well, rather than using GetInternalValue(). Same with new_stub.
EDIT: You need essentially to do the following (note I'm not sure if this is the correct syntax as I haven't used that framework, but I'm trying to capture the essence):
previous_date.Stub(x => x.Value).Return("20160525");

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

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

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);

Categories

Resources