How to setup methods which return a built-in type and implement IEnumerable interface in Moq ?
Rajmond Burgaj
Posted on September 10, 2018
Recently I was trying to make some unit testing and at some point I realized something was going wrong with my design but at the same time could not change it. So, the idea is I am using entity framework and executing stored procedures using this framework. All these procedures were encapsulated inside a service called IProcedureService
.So, a normal method would look like this:
DbRawSqlQuery<UserVesselPermissionsResult> GetUserVesselPermissions(Guid userId, DateTime date);
The DbRawSqlQuery
is an class from entity framework which I can not modify. The question for me was, how I am going to make this Moq
setup code work:
_procedureService.Setup(x => x.GetUserVesselPermissions(It.IsAny<Guid>(), It.IsAny<DateTime>()))
.Returns((DbRawSqlQuery<UserVesselPermissionsResult>) /*...what*/);
The real problem was due to class itself having only one internal constructor which could not be instantiated in Moq
. That's because Moq
can not instantiate classes only with internal constructor. Further more this class could have constructors with some parameters which I can not supply at this point(an example could be a DbConnection or something similar). In this case I tried to decompile the source and I could see another class named DbSqlQuery
which was inheriting from DbRawSqlQuery
and provided a normal constructor besides the internal one. At this point, I found an idea how to make this work. The idea was to create a new class and inherit from DbSqlQuery
. My class now would look like this:
public class TestDbSqlQuery<T> : DbSqlQuery<T> where T : class
{
private readonly List<T> _innerList;
public TestDbSqlQuery(List<T> innerList)
{
_innerList = innerList;
}
public override IEnumerator<T> GetEnumerator()
{
return _innerList.GetEnumerator();
}
}
As you can from the code now I have achieved two things:
- I do have a class inheriting from
DbRawSqlQuery
which is what I need. - Secondly I do have a class which can be instantiated and furthermore does accept a parameter in constructor which then can be tricked internally.
By tricked internally I mean this: - Since my methods all returned DbRawSqlQuery
which at the end is just an IEnumerable
type, then I thought all of these will be executing GetEnumerator()
method to get the result. At this point I have provided a list as a parameter in the constructor from where I can easily return all the elements by overriding the GetEnumerator()
method as I did above. I have a List<>
as a parameter but this can be easily switched accordingly to IEnumerable
or whatever type that supports GetEnumerator()
method.
Now my test method setup would look like this:
_procedureService.Setup(x => x.GetUserVesselPermissions(It.IsAny<Guid>(), It.IsAny<DateTime>()))
.Returns(new TestDbSqlQuery<UserVesselPermissionsResult>(new List<UserVesselPermissionsResult>
{
new UserVesselPermissionsResult
{
PermissionId = 1
}
}));
and I will get the expected result at the end.
Hopefully this idea will help somebody struggling with setting up the methods which do return IEnumerable
types.
Posted on September 10, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
September 10, 2018