-
Notifications
You must be signed in to change notification settings - Fork 179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proxy methods calls to real implementation #435
Comments
I'd commented in error earlier. 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 Fake > 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 A.CallTo(fake).Invokes(…); // or
A.CallTo(fake).WithReturnType<bool>(…); |
Thanks for the answer. Replaced Configure with the A.Callto syntax. Since not all is overridable I used following approach to support all of my codepaths easily. public static TFake Proxy<TFake, TInstance>(TFake fake, TInstance instance) where TInstance : TFake
{
ProxyReturnType<TFake, TInstance, int>(fake, instance);
ProxyReturnType<TFake, TInstance, bool>(fake, instance);
ProxyReturnType<TFake, TInstance, string>(fake, instance);
ProxyReturnType<TFake, TInstance, Contact>(fake, instance);
ProxyReturnType<TFake, TInstance, Instance>(fake, instance);
ProxyReturnType<TFake, TInstance, PostItem>(fake, instance);
ProxyReturnType<TFake, TInstance, SpaceItem>(fake, instance);
ProxyReturnType<TFake, TInstance, Notification>(fake, instance);
ProxyReturnType<TFake, TInstance, Reaction>(fake, instance);
ProxyReturnType<TFake, TInstance, GoodAnswer>(fake, instance);
ProxyReturnType<TFake, TInstance, SmartList>(fake, instance);
A.CallTo(fake).Where(x => x.Method.ReturnType == typeof(void)).Invokes(x => x.Method.Invoke(instance, x.Arguments.ToArray()));
return fake;
}
private static void ProxyReturnType<TFake, TInstance, TMethodReturnType>(TFake fake, TInstance instance) where TInstance : TFake
{
A.CallTo(fake).WithReturnType<TMethodReturnType>().ReturnsLazily(x => (TMethodReturnType)x.Method.Invoke(instance, x.Arguments.ToArray()));
A.CallTo(fake).WithReturnType<IQueryable<TMethodReturnType>>().ReturnsLazily(x => (IQueryable<TMethodReturnType>)x.Method.Invoke(instance, x.Arguments.ToArray()));
A.CallTo(fake).WithReturnType<IEnumerable<TMethodReturnType>>().ReturnsLazily(x => (IEnumerable<TMethodReturnType>)x.Method.Invoke(instance, x.Arguments.ToArray()));
A.CallTo(fake).WithReturnType<ICollection<TMethodReturnType>>().ReturnsLazily(x => (ICollection<TMethodReturnType>)x.Method.Invoke(instance, x.Arguments.ToArray()));
A.CallTo(fake).WithReturnType<IList<TMethodReturnType>>().ReturnsLazily(x => (IList<TMethodReturnType>)x.Method.Invoke(instance, x.Arguments.ToArray()));
A.CallTo(fake).WithReturnType<List<TMethodReturnType>>().ReturnsLazily(x => (List<TMethodReturnType>)x.Method.Invoke(instance, x.Arguments.ToArray()));
A.CallTo(fake).WithReturnType<Task<TMethodReturnType>>().ReturnsLazily(x => (Task<TMethodReturnType>)x.Method.Invoke(instance, x.Arguments.ToArray()));
A.CallTo(fake).WithReturnType<Task<ICollection<TMethodReturnType>>>().ReturnsLazily(x => (Task<ICollection<TMethodReturnType>>)x.Method.Invoke(instance, x.Arguments.ToArray()));
}
public static TFake Proxy<TFake, TInstance>(TInstance instance) where TInstance : TFake
{
var fake = A.Fake<TFake>();
return Proxy(fake, instance);
} It can be used as following var actual = new SomeClass(); //Someclass implements ISomeInterface
return Proxy<ISomeInterface, SomeClass>(actual); |
@marcofranssen, I am not sure if you are content with your solution or not, although the public class SomeClass : ISomeInterface
{
public string GetName()
{
return "SomeClass";
}
}
public interface ISomeInterface
{
string GetName();
}
[Test]
public void Can_use_proxy_method_to_make_wrapping_fake()
{
var actual = new SomeClass(); //Someclass implements ISomeInterface
var proxy = Proxy<ISomeInterface, SomeClass>(actual);
Assert.That(proxy.GetName(), Is.EqualTo("SomeClass"));
}
[Test]
public void Can_wrap_a_fake_using_builtin_mechanism()
{
var actual = new SomeClass(); //Someclass implements ISomeInterface
var proxy = A.Fake<ISomeInterface>(options => options.Wrapping(actual));
Assert.That(proxy.GetName(), Is.EqualTo("SomeClass"));
} Unless there's a failing in the built-in wrapper, it might be able to save you some aggravation, especially if your classes start working with more types. |
@marcofranssen Can we conclude that you're satisfied with your answer? If everything's working great for you, we're happy, but the corollary to my last comment is that if there is a failing in the built-in wrapper, we'd be grateful to have it explained so we can try to rectify it, for everyone's benefit. |
Somehow missed the wrapper method. Still need to test that one. Keep you posted. Thanks for the help so far. |
From @marcofranssen's comment and acceptance of my answer to the Stack Overflow question, it seems that |
Great! |
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.
I would use that like this.
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<T, TReturn>)Then I was trying to do this using the WithReturnValue method.
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? Could we add a
Proxy
method to FakeItEasy in a future version?For the latter it maybe would be cool to have it available something more fluent like.
The text was updated successfully, but these errors were encountered: