Skip to content
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

Mock's members incorrectly marked as non-final #141

Closed
dcastro opened this issue Nov 12, 2014 · 2 comments
Closed

Mock's members incorrectly marked as non-final #141

dcastro opened this issue Nov 12, 2014 · 2 comments
Labels

Comments

@dcastro
Copy link

dcastro commented Nov 12, 2014

Prior to version 4.2.1408.619, proxies generated for a class had the same exact methods with the exact same signature as the class being proxied. This is the expected behaviour.

Starting in 4.2.1408.619, under some circumstances, some proxies might have their methods marked as virtual non-final (i.e., overridable), whereas the method of the object being proxied is in fact virtual final (i.e., sealed).

This seems like a bug to me - I'd like to get the maintainers and owners' opinions on this please.

Test Case

public interface ISomeInterface
{
    void Method();
}

public class ConcreteClass : ISomeInterface
{
    public void Method() { }
}

public class Test
{
    [Fact]
    public void SomeTest()
    {
        //print the SUT's methods
        Console.WriteLine("----- Printing the ConcreteClass's methods -----");
        PrintMethod(typeof(ConcreteClass));

        //print the proxy's methods
        Console.WriteLine("----- Printing the proxy's methods -----");
        var mock = new Mock<ConcreteClass>();
        PrintMethod(mock.Object.GetType());
    }

    public void PrintMethod(Type type)
    {
        var method = type.GetMethod("Method");

        Console.WriteLine("Declaring Type: " + method.DeclaringType);
        Console.WriteLine("IsVirtual: " + method.IsVirtual);
        Console.WriteLine("IsFinal: " + method.IsFinal);
    }
}

Output using Moq 4.2.1402.2112 (correct and works as expected):

----- Printing the ConcreteClass's methods -----
Declaring Type: Ploeh.AutoFixture.AutoMoq.UnitTest.ConcreteClass
IsVirtual: True
IsFinal: True
----- Printing the proxy's methods -----
Declaring Type: Ploeh.AutoFixture.AutoMoq.UnitTest.ConcreteClass
IsVirtual: True
IsFinal: True

Output using Moq 4.2.1408.619 (unexpected output):

----- Printing the ConcreteClass's methods -----
Declaring Type: Ploeh.AutoFixture.AutoMoq.UnitTest.ConcreteClass
IsVirtual: True
IsFinal: True
----- Printing the proxy's methods -----
Declaring Type: Castle.Proxies.ConcreteClassProxy     <------------- I have no idea why this isn't ConcreteClass
IsVirtual: True
IsFinal: False                                        <------------- should be True

If this bug was introduced by Castle's Dynamic Proxy and not Moq, let me know and I'll report this on their page.

If this is not a bug and is actually by design, it seems like a breaking change to me - the signature of a public method of a public type was changed.

For a bit more context, see this issue on AutoFixture GitHub page.

PS: FYI, the same does not happen when ISomeInterface is a class instead of an interface, and Method is marked as virtual in the base class and sealed override in the derived class.

@stakx
Copy link
Contributor

stakx commented Jun 16, 2017

Sorry about the tagging. This sounds like a DynamicProxy-related problem, however it seems that both Moq versions that you mentioned used the same DynamicProxy version (3.2.0).

@stakx
Copy link
Contributor

stakx commented Jun 20, 2017

Fixed in Moq 4.7.58.

@stakx stakx closed this as completed Jun 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants