-
Notifications
You must be signed in to change notification settings - Fork 7
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
Non-substitutable (non-virtual) member are sometimes still substitutable in extension methods #170
Comments
Yes, this is limitation of NSubstitute. Analyzers. We dont even try to detect such cases, as this kind of analysis will be simply too expensive both in terms of memory/cpu usage and implementation time/complexity. For advanced users who "know what they are doing", we allow to configure analyzers to ignore certain rules for specific members. See more details in |
Hi @tpodolak !
No. Whether it works or not depends on how the extension method delegates to a substitute, and whether the extension return matches the value returned from the call to the substitute. Whenever I've done this in the past I've considered it a bit of a hack based on knowing the internals of how NSubstitute works. The same trick can work with non-virtual calls to class members too -- if they forward to a virtual protected member then we can sometimes mock that protected member via the non-virtual call. I think I'd prefer to discourage this practice via Analyzers as we can't reliably mock static members, and for people that are confident a particular case will work then they can suppress the error. Maybe we can make it easier to do this by having a separate error for not being able to reliably substitute for extension methods, so that can be suppressed separately from standard non-virtual calls? |
Hi @rklec ,
It sort of works by accident. For a contrived example: public static int AddOne(this ICalculator c, int value) => c.Add(value, 1); If we test this like: var c = Substitute.For<ICalculator>();
c.AddOne(42).Returns(100); NSubstitute does not see the |
Thanks a lot for all your detailed answers! Personally, I'd also say you could adjust the doc/(new) error message or so, to state that in some circumstances it may work or so. |
@dtchepak we have 3 different warnings for non-virtual member usages Should we add 3 additional warnings for extension method usage to align with that convention (one for |
@tpodolak I guess it makes sense to follow that convention. Alternatively maybe we can merge NS1000 and NS1002? |
I think this should be possible(will double check just in case) and merge them once I start working on this one. |
NS1000 and NS1001 sometimes lie.
At least, sometimes NSubstitute can actually substitute the methods correctly.
I don't quite get/know why this works, because I agree with the warning that it should not work, but it seems that it can successfully work on Extension methods (which by definiton cannot be virtual or so of course) if they are on an interface.
Code to reproduce that runs through without any error, only NSubstitute.Analyzers complains:
Warnings
System
DotNet Core 3.1
Dependencies:
The text was updated successfully, but these errors were encountered: