Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FakeItEasy Proxy methods calls to real implementation

I'm trying to proxy calls to a fake object to the actual implementation. The reason for this is that I want to be able to use the WasToldTo and WhenToldTo of Machine.Specifications which only works on fakes of an interface type.

Therefore I'm doing the following to proxy all calls to my real object.

public static TFake Proxy<TFake, TInstance>(TFake fake, TInstance instance) where TInstance : TFake
{
    fake.Configure().AnyCall().Invokes(x => x.Method.Invoke(instance, x.Arguments.ToArray()));
    return fake;
}

I would use that like this.

var fake = Proxy<ISomeInterface, SomeImplementation>(A.Fake<ISomeInterface>(), new SomeImplementation());

//in my assertions using Machine.Specifications (reason I need a fake of an interface)
fake.WasToldTo(x => x.DoOperation());

The problem however is that this only works for void methods, since the Invokes method is not doing anything with the return value. (Action param instead of Func)

Then I was trying to do this using the WithReturnValue method.

public static TFake Proxy(TFake fake, TInstance instance) where TInstance : TFake
{
    fake.Configure().AnyCall()..WithReturnType().Invokes(x => x.Method.Invoke(instance, x.Arguments.ToArray()));
    fake.Configure().AnyCall()..WithReturnType().Invokes(x => x.Method.Invoke(instance, x.Arguments.ToArray()));
    fake.Configure().AnyCall()..WithReturnType().Invokes(x => x.Method.Invoke(instance, x.Arguments.ToArray()));
    //etc.
    return fake;
}

However the Invokes method still doesn't work the way I want it (still Action instead of Func). So The return value is still not used.

Is there a way of achieving this with the current latest version?

I already filed an issue at the FakeItEasy github repository. https://github.com/FakeItEasy/FakeItEasy/issues/435

like image 540
Marco Avatar asked Jan 13 '15 14:01

Marco


Video Answer


1 Answers

Stealing from my response at the FakeItEasy github repository:

You can create a fake to wrap an existing object like so:

var wrapped = new FooClass("foo", "bar");
var foo = A.Fake<IFoo>(x => x.Wrapping(wrapped));

(example taken from Creating Fakes > Explicit Creation Options)

That should delegate all calls to the underlying object, with the usual caveat that any redirected calls have to be overrideable.

I hope this helps. If not, come back and explain again. Maybe I'll understand it better.

Oh, and beware the Configure mechanism. It's going away in FakeItEasy 2.0.0. The preferred idiom is

A.CallTo(fake).Invokes(…); // or
A.CallTo(fake).WithReturnType<bool>(…); 
like image 54
Blair Conrad Avatar answered Sep 25 '22 16:09

Blair Conrad