This is my first attempt at something like this, so hopefully this is simple.
I have created a WCF service which uses Entity Framework to access the database. I have implemented a UnitOfWork interface so my service can use EF while still being testable.
Here is my service:
public class ProjectService : IProjectService
{
private IUnitOfWork db = null;
public ProjectService(IUnitOfWork unitofwork)
{
db = unitofwork;
}
public int RegisterSite(int CPUID)
{
if (db.Servers.Count(x => x.CPUID == CPUID) > 0)
{
// do something
}
return 0;
}
}
Here is my UnitOfWork interface:
public interface IUnitOfWork
{
IObjectSet<tblClient> Clients { get; }
IObjectSet<tblServer> Servers { get; }
IObjectSet<tblSite> Sites { get; }
IObjectSet<tblServerLog> ServerLogs { get; }
void Commit();
}
When I use this Service with either concrete implementations of a SQLUnitOfWork
(using EF) or with a InMemoryUnitOfWork
(just in memory objects) then it works fine.
After testing fine with my in memory objects i tried this test.
[Test]
public void RegisterAnExistingServer()
{
MockRepository mocks = new MockRepository();
IUnitOfWork MockUnitOfWork = mocks.DynamicMock<IUnitOfWork>();
ProjectService service = new ProjectService(MockUnitOfWork);
Expect.Call(MockUnitOfWork.Servers.Count(x => x.CPUID == 1234)).Return(0);
mocks.ReplayAll();
int NewSiteID = service.RegisterSite(1234);
mocks.VerifyAll();
}
But when I try using it in Rhino Mock with an Expectation on Servers.Count I get the following error:
System.ArgumentNullException : Value cannot be null.
Parameter name: arguments
at System.Linq.Expressions.Expression.RequiresCanRead(Expression expression, String paramName)
at System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi)
at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ref ReadOnlyCollection`1 arguments)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
at System.Linq.Queryable.Count(IQueryable`1 source, Expression`1 predicate)
What am I doing wrong??
There is probably some reflection going on internally and hence you are not getting a straight forward call to your unit of work.
I strongly suggest switching to nhibernate. Also, ditch WCF.
MikeEast is correct. Rhino.Mocks doesn't do recursive mocking. You need to mock up the Servers property to return something (just create an empty IObjectSet<tblServer> and set that up as the return value).
Also, you don't want to set expectations on lambdas. Once everything gets compiled, the lambda in your code and the lambda in your unit test are two totally different methods (and your expectation will always fail). See http://groups.google.com/group/rhinomocks/msg/318a35ae7536d90a for more details.