5

How would you go about faking the following:

public interface IBlah
{
    Func<T, bool> ApplyFilter<T>(Func<T, bool> predicate) where T:IMessage;
}

What I would like is for the fake to simply return it's argument without any changes. However, I would like to verify that the fake has been called exactly once. A use case is given below:

  public class Something
  {

     public Something(IBlah blah) { _blah = blah; }

     public bool DoSomething(SomeValue m, Func<SomeValue, bool> predicate)
     {
         Func<SomeValue, bool> handler = _blah.ApplyFilter(predicate);
         return handler(m);
     }
  }

i.e. the fake needs to act as a pass through but I also need to be able to verify it's been used.

What's the best way to go about this?

[Please don't worry about the contrived example...there's a lot of things going on under the covers, but I've simplified it down to the example above.]

ashic
  • 6,367
  • 5
  • 33
  • 54
  • 1
    Do you want to verify that it's used no more than once, used at least once, or used exactly once? What should happen if it doesn't meet that condition? Should that interface have a `numInvocations` property? You can verify it won't be called *more* than once easily enough, but knowing if it hasn't been called...you need a way to provide feedback. – Servy Feb 07 '13 at 18:39
  • Without generics involved, I can do the same with var fake = A.Fake(); A.CallTo(()==> fake.SomeMethod(A._)) .ReturnsLazily(x=>x.GetArgument(0)); .... A.CallTo(fake).MustHaveHappened(Repeated.Exactly.Once); I can't figure out how to do the same with the Func generic being there. I've tried creating a Dummy implementation of the interface, and that can do the pass through, but since that's concrete, FakeItEasy can't verify that it was used. – ashic Feb 07 '13 at 18:43
  • So given that you need to ensure it's happened exactly once you'll want the method to return a class that has two properties, `NumInvokations` and this function. Pass the function on elsewhere, then determine if `NumInvokations` is equal to one afterwards. – Servy Feb 07 '13 at 18:46
  • So you mean a dummy implementation would be: class Dummy : IBlah { public int Invocations; public Func ApplyFilter(Func handler) { Invocations++; return handler; } } The problem is this particular thing will be nested in another fake..I was hoping FakeItEasy would be able to do the mock without having to hand craft this. – ashic Feb 07 '13 at 18:49

1 Answers1

2

Would this solve your issue? It will pass through the predicate and also verify that ApplyFilter was called exactly once

    [Fact]
    public void TestFeature()
    {
        var fake = A.Fake<IBlah>();
        A.CallTo(() => fake.ApplyFilter(A<Func<int, bool>>.Ignored)).ReturnsLazily(x =>
            {
                return x.GetArgument<Func<int, bool>>("predicate");
            });
        var something = new Something(fake);
        var result = something.DoSomething(1, x => x > 1);

        Assert.False(result);
        A.CallTo(() => fake.ApplyFilter(A<Func<int, bool>>.Ignored)).MustHaveHappened(Repeated.Exactly.Once);
    }
cecilphillip
  • 11,446
  • 4
  • 36
  • 40
  • While that would work while specifying the T to be int, I'm looking for a generic version that should work for any type. The following kind of shows what I'm trying to achieve: http://pastebin.com/fJgi6ikj In other words, the fake should work for *any* IMessage, without having to specify the exact type. – ashic Feb 08 '13 at 22:03