1

How do you fake a class with FakeItEasy that implements multiple interfaces.

e.g. A class that implements both IFoo and IBar

I've tried the following but it doesn't work

A.Fake<IFoo>(builder => builder.Implements<IBar>());
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
EC99
  • 137
  • 10
  • That's the way. Can you expand on "doesn't work"? What happens when you try it? What doesn't work? What's the compiler or runtime output? What version of FakeItEasy are you using? (Also consider reviewing https://stackoverflow.com/help/how-to-ask for future questions.) – Blair Conrad Aug 22 '23 at 15:43
  • When I try and set properties of IBar, FakeItEasy doesn't have any knowledge of any properties of IBar's class. Renat below is correct. – EC99 Aug 23 '23 at 07:39
  • Yeah, @Renat's answer is excellent. But it's not FakeItEasy that doesn't know about the `IBar` members, it's C#. The compiler can only work with the types presented to it. – Blair Conrad Aug 23 '23 at 14:08
  • If you had a concrete class that implemented both `IFoo` and `IBar` e.g. `public class Example : IFoo, IBar` the compiler would be ok with that. I would have hoped using the builder would emulate this concrete class but perhaps I'm not thinking this through properly – EC99 Aug 23 '23 at 14:52

1 Answers1

3

Well, it actually works, if do type casting. A.Fake<IFoo>(...) returns IFoo, and FakeItEasy simply knows nothing about any aggregate type/interface which would implement both IFoo and IBar, hence manual type casting to IBar is required.

public static void Main()
{
    var o = A.Fake<IFoo>(builder => builder.Implements<IBar>());
    
    A.CallTo(() => o.A())
         .Invokes(() => Console.WriteLine("I'm IFoo.A()"));
    A.CallTo(() => ((IBar)o).B())
         .Invokes(() => Console.WriteLine("I'm IBar.B()"));

    o.A();
    var oAsBar = (IBar)o;
    oAsBar.B();
}

public interface IFoo
{
    void A();
}
public interface IBar
{
    void B();
}

produces

I'm IFoo.A()
I'm IBar.B()
Renat
  • 7,718
  • 2
  • 20
  • 34