lucisferre

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult. —Sir Charles Antony Richard Hoare”

Mocking Methods With Lambda Predicates Parameters

lambdareflection

I often work with lambda’s, as I’ve mentioned before I am a bit of a LINQ junkie. As a result I have started creating methods that takes predicates as parameters, however I was finding methods like this difficult to mock. It took a bit of doing but I finally managed to figure this out.

I have such methods defined in an interface like this:

1
2
3
4
5
6
7
8
9
public interface ILinqRepository<T> {
  void Delete(T target);
  T FindOne(int id);
  T FindOne(Expression<Func<T, bool>> predicate);
  IQueryable<T> FindAll();
  IQueryable<T> FindAll(Expression<Func<T, bool>> predicate);
  void Save(T entity);
  void SaveAndEvict(T entity);
}

Now say I have a test for finding a particular entity from my repository

1
2
3
4
5
[Test]
public void CanGetSecurityByISMNumber() {
  _securityRepository.Stub(m => m.FindOne(null)).IgnoreArguments().Return(TestData.Security);
  Assert.That(_tasks.GetSecurityByISMNumber(TestData.Security.IBMSecurityNumber) == TestData.Security);
}

A pretty simple test where I am using some static TestData with the mock. However the problem I have with this test is that this test is not driving the design I want (TDD right), I am not actually testing what I want to test. I could implement GetSecurityByISMNumber to call FindOne with any predicate value and make this pass.

Instead what I can do is use RhinoMocks Callback feature like this:

1
2
3
4
5
6
7
8
[Test]
public void CanGetSecurityByISMNumber() {
  _securityRepository.Stub(m => m.FindOne(null))
    .IgnoreArguments()
    .Callback<Expression<Func<Security, bool>>>(p => p.Compile().Invoke(TestData.Security))
    .Return(TestData.Security);
  Assert.That(_tasks.GetSecurityByISMNumber(TestData.Security.IBMSecurityNumber) == TestData.Security);
}

Perhaps a tad bit messy but I think it communicates my design intent clearly. I could also factor out the lambda there into it’s own function like QueryIsValid

1
2
3
private static bool QueryIsValid(Expression<Func<Security,bool>> predicate) {
  return predicate.Compile().Invoke(TestData.Security);
}

I should also note that if I wasn’t using Expression here I could skip the call to Compile which would make it a bit more readable.

Comments