Closed ahausmann closed 7 years ago
Hi @ahausmann,
Thanks for the report and the great sample case. I think the problem is the proxy class is not fully constructed when the virtual method is called, so the GetFoo()
call in the TestClass
constructor returns null
instead of the proxy being able to delegate it back to the base class. The guidelines from MSDN suggest not calling virtual members in constructors for this reason.
I'm not sure the NSubstitute code can do much about this? (happy to be proven wrong :) )
Well, when I tested it using Moq it worked. And afaik both NSubstitute and Moq use the Castle Proxy library, but correct me if I'm wrong.
Testcode for Moq:
public class TestClass
{
public TestClass()
{
Debug.WriteLine (GetFoo ());
}
public virtual string GetFoo() {
return "foo";
}
public static void Main (string[] args)
{
Mock<TestClass> mock = new Mock<TestClass> ();
mock.CallBase = true;
TestClass a = mock.Object ;
Debug.WriteLine (a.GetFoo ());
}
}
And the output:
foo
foo
So it doesn't seem to be a problem with having the virtual method call in the constructor.
P.S. Yes I'm aware that it's bad to call virtual methods, but as I said it's a third-party class that I can't change.
Yes both use Castle Dynamic Proxy.
Does new Mock<TestClass>
call the TestClass constructor? Or does that
happen when mock.Object
gets called?
On 27 Jun 2015 1:46 am, "Alexander Hausmann" notifications@github.com
wrote:
Well, when I tested it using Moq https://github.com/Moq/moq4 it worked. And afaik both NSubstitute and Moq use the Castle Proxy library, but correct me if I'm wrong.
Testcode for Moq:
public class TestClass { public TestClass() { Debug.WriteLine (GetFoo ()); }
public virtual string GetFoo() { return "foo"; } public static void Main (string[] args) { Mock<TestClass> mock = new Mock<TestClass> (); mock.CallBase = true; TestClass a = mock.Object ; Debug.WriteLine (a.GetFoo ()); }
}
And the output:
foo foo
So it doesn't seem to be a problem with having the virtual method call in the constructor.
P.S. Yes I'm aware that it's bad to call virtual methods, but as I said it's a third-party class that I can't change.
— Reply to this email directly or view it on GitHub https://github.com/nsubstitute/NSubstitute/issues/188#issuecomment-115736996 .
Sorry for the late response.
The constructor is called when the mock.Object property is called the first time.
I had a more detailed look at this. We deliberately disabled interception of calls during construction to fix issue #57.
It may be possible to pass through whether we are creating a partial sub proxy, and call base by default during constructor of the proxy for those cases, then swap back to the standard interceptor behaviour. (The proxy is created in CastleDynamicProxyFactory.cs.)
Closing as part of a general cleanup of issues. Please re-open if any action is required.
Hi, I have a third-party class that calls a virtual method in its constructor. When I tried to create a substitute for the class the virtual method returned the default value (or in the case below string.Empty).
Example Code:
The code above prints the following to the output window
but I expected to get
Edit: Grammar fixes