15

I wonder if there is anyway one can fake up a generic method call, for all possible types (or specified sub-types)?

For example, suppose we have this wonderful IBar interface.

public interface IBar
{
    int Foo<T>();    
}

Can I fake a dependency to this IBar's Foo call, without having to specify T being any specific type?

[TestFixture]
public class BarTests
{
    [Test]
    public void BarFooDoesStuff()
    {
        var expected = 9999999;
        var fakeBar = A.Fake<IBar>();

        A.CallTo(() => fakeBar.Foo<T>()).Returns(expected);

        var response = fakeBar.Foo<bool>();

        Assert.AreEqual(expected, response);
    }
}

Thanks!

Rokey Ge
  • 681
  • 8
  • 18

1 Answers1

23

I'm not aware of any way to do this directly. I don't think DynamicProxy (which FakeItEasy uses) supports open generic types. However, there's a workaround, if you're interested.

There's a way to specify a call to any method or property on a fake. Check out the Where and WithReturnType bits in this passing test:

[TestFixture]
public class BarTests
{
    [Test]
    public void BarFooDoesStuff()
    {
        var expected = 9999999;
        var fakeBar = A.Fake<IBar>();

        A.CallTo(fakeBar)
            .Where(call => call.Method.Name == "Foo")
            .WithReturnType<int>()
            .Returns(expected);

        var response = fakeBar.Foo<bool>();

        Assert.AreEqual(expected, response);
    }
}

Still, though, I'm curious about the use for this. Do you have an example test that actually uses the faked interface as a dependency?

Blair Conrad
  • 233,004
  • 25
  • 132
  • 111
  • 1
    +1 this is a good way to do it, but I'm also unconvinced of the need to set up a fake in this manner. a unit test should generally close the type parameter on a generic – Adam Ralph Apr 06 '14 at 00:45
  • Very nice! I don't have specific examples to show... more for the curiosity whether something like this can be done (easily). Perhaps Reflection can be employed to restrict the generic types in the fake set-up? – Rokey Ge Apr 07 '14 at 11:13
  • @AdamRalph yes, but is doesn't necessarily have to do this in a static manner. I for example am using SpecFlow and I have steps like `When with Id is retrieved from repository`. With the above I don't have to prepare a step binding method for each . – Tomasz Pluskiewicz Dec 16 '14 at 07:59
  • I just used this to make all my validation helper methods pass by default in unit tests. `A.CallTo(validationService).WithReturnType().Returns(true);` I can later override one method with specific behavour if needed. – Buh Buh May 18 '15 at 15:46
  • 2
    If you are using C#6 then you could make it easier to refactor, by using "nameof": `A.CallTo(fakeBar).Where(call => call.Method.Name == nameof(fakeBar.Foo)).WithReturnType().Returns(expected);` – Lech Osiński Jan 30 '17 at 13:21
  • It's a pretty old answer, but I have an example usage : I have a `IExporter` using a `ISerializer` with methods to serialize various objects. In my `Exporter` tests, I don't care about what the serializer returns, but I don't want it to return an empty string. So I'm using `A.CallTo(serializer).WithReturnType().Returns(fixture.Create());` but if I add a non-serializing method to `ISerializer` later my tests might break. – thomasb May 05 '17 at 10:32