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

Setup does not throw NotSupportedException when setting up sealed method seen through an interface #453

Closed
stakx opened this issue Sep 22, 2017 · 1 comment

Comments

@stakx
Copy link
Contributor

stakx commented Sep 22, 2017

This is a continuation of #452 (reported by @toha73).

public interface IInterface
{
    string Answer { get; }
}

public class Implementation : IInterface
{
    public string Answer => "answer from implementation";  // note: non-overridable!
}

[Fact]
void Setup_throws_NotSupportedException_when_given_sealed_method()
{
    // Arrange:
    Implementation mockedImplementation = Mock.Of<Implementation>();
    Mock<IInterface> mock = Mock.Get<IInterface>(mockedImplementation);

    // Act:
    var error = Record.Exception(() =>
    {
        mock.Setup(_ => _.Answer).Returns("mocked answer");
    });

    // Assert:
    Assert.NotNull(error);
    Assert.IsType<NotSupportedException>(error);
}

This test creates a mock Implementation, then tries to set up Answer by looking at the mock through the IInterface interface. This setup should fail because Implementation.Answer is sealed, i.e. non-overridable, and therefore non-interceptable.

However, the test currently fails, i.e. the setup (incorrectly) runs to completion without any error. This would probably suggest to most people that the setup will take effect, yet that is not the case: proxy.Answer will (correctly) still return "answer from implementation" and not "mocked answer".

In more straightforward usages, such as new Mock<Implementation>().Setup(_ => _.Answer), Moq correctly recognizes that Implementation.Answer is non-overridable and throws.

The problem here is that Moq only sees IInterface.Answer and doesn't verify what target method (Implementation.Answer) this interface method might map to for the given mock, and whether that target method might be sealed.

This problem can only surface when mocking classes. It can't happen when mocking an interface directly.

The problem also isn't unique to just Setup. For example, SetupGet is likewise affected.

@stakx stakx added the bug label Sep 22, 2017
@stakx stakx added this to the v4.9.0 milestone Dec 8, 2017
@stakx stakx removed this from the v4.9.0 milestone Feb 26, 2018
@stakx
Copy link
Contributor Author

stakx commented Jul 13, 2018

Closing this dormant issue, but marking it as "unresolved" so it can be easily found again. Please see #642 for details. If you'd like to pick this up and work on it, please post here briefly and we'll see what we can do!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant