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

Update from 4.13.1 to 4.16.1 generic method setup fails #1243

Closed
b3go opened this issue Mar 15, 2022 · 2 comments
Closed

Update from 4.13.1 to 4.16.1 generic method setup fails #1243

b3go opened this issue Mar 15, 2022 · 2 comments

Comments

@b3go
Copy link

b3go commented Mar 15, 2022

created from #1217 @stakx

  • Setup generic methods with derived interfaces
    The test setups a generic method twice, first with the derived interface and then with the base interface and for either setup it returns differnt object. Before the update it worked like that without issues but after the update only the setup for the base interface was used. After I changed the registration order, to first setup with the base interface and then with the derived interface, it again worked like a charm. I guessed that the setup with the base interface somehow overwrites the setup with the derived one. Is this intended?

Example:

void Main()
{
	var mock = new Mock<IResolver>();
	mock.Setup(x => x.Resolve<IFooController>()).Returns(() => new Mock<IFooController>().Object);
	mock.Setup(x => x.Resolve<IController>()).Returns(() => new Mock<IController>().Object);

	var controller = mock.Object.Resolve<IController>();
	Console.WriteLine(controller.GetType());

	// in 4.13.1: works
	// in 4.16.1: InvalidCastException: Unable to cast object of type 'Castle.Proxies.IControllerProxy' to type 'IFooController'.
        // works in 4.16.1 if I switch the two setup rows with each other.
	var fooController = mock.Object.Resolve<IFooController>();
	Console.WriteLine(fooController.GetType());
}

public interface IResolver
{
	T Resolve<T>();
}
public interface IController
{
}
public interface IFooController : IController
{
}

Again there is no real issue anymore, quoting myself:

I just want to let you know there was a breaking change, somewhere between 4.13.1 and 4.16.1, which doesn't show up in the documentation.

Thank you for your work!

@stakx
Copy link
Contributor

stakx commented Mar 16, 2022

Ah yes, I suspected as much. We've had a few similar reports. Whenever this issue shows up, my suggestion is to order setups from least specific to most specific... a rule that always applied and in recent versions also applies to generic type arguments.

Say you had these setups:

mock.Setup(m => m.Method(42))...;
mock.Setup(m => m.Method(It.IsAny<int>()))...;

The first (more specific) setup would essentially be shadowed by the second (less specific) one.

The same thing now happens with generic type arguments: a IFooController is a IController but not vice versa, so the less specific setup (for IController) should go first.

@b3go
Copy link
Author

b3go commented Mar 16, 2022

Thanks for the reply, if that's something that is reported from time to time, maybe you could consider including that case in the documentation?

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

2 participants