Closed jcansdale closed 7 years ago
Hi @jcansdale,
If these are the only two methods on the interface (or the only two that return object
) you could try the ReturnsForAll
extension. Bit of a hack but might work. Other than that, as far as NSubstitute knows these are two completely different methods so they'd generally need to be stubbed separately.
Arg, that's a shame. I'm substituting some pretty big and complex interfaces. 😢
The trick I was using with TypeMock was to create an interface that implements all of my target interfaces and mock that. Something like this:
using EnvDTE;
public interface MyCodeClass : CodeClass, CodeElement, CodeType
{
}
Alas this doesn't work with NSubstitute and CodeClass, CodeElement, CodeType end up with separate implementations.
Apart from this the conversion has gone very smoothly! 😄
Sorry the final mile hasn't been that smooth, but happy to hear things went pretty well in general. :)
If you need to do a lot of this you could try hacking something up with reflection.
For all members on IServiceProvider
, delegate matching calls on ServiceProvider
to that instance:
// Pseudocode
TTarget sub = ...
TDelegator delegator = ...
foreach member of typeof(TTarget):
if delegator has matching member and non-void:
invoke member on delegator
SubstituteExtensions.Returns(delegator, x => invoke member on sub)
else if delegator has matching member:
wire up to When..Do
This would be pretty terrible for test performance I'm guessing, but I think it would work.
I'm not sure how to support this feature properly from NSubstitute. :-\ I'm open to any ideas :)
@dtchepak,
Thanks for your reply. I just had another look to see what I could come up with. I've stumbled across a workaround that, while not pretty, isn't error prone like what I was doing before (defining returns individually for each interface).
If I define a new abstract class like this:
public abstract class ACodeClass : CodeClass, CodeElement, CodeType
{
}
Ctrl-. offers an option that I'd never seen before: "Implement interface abstractly". If I do this and then substitute for this abstract class, the interfaces will be implemented implicitly. Although verbose, this works out fine. :smile:
Ideally this behavior would be the default when doing Substitute.For
. Although I've know about explicitly implemented interfaces for a long time, I'm not sure I've ever seen them actually used in the wild. If it's tricky or potentially a breaking change, maybe the above workaround could be put in the FAQ? Substituting COM interfaces is a pretty great use-case and I expect this situation/gotcha is pretty common.
Thanks again for your work on NSubstitute. It really has been a pleasure to use. 😄
BTW, I've been working on a library for mocking static methods, that has ended up integrating perfectly with NSubstitute. If you're interested, I've put a simple getting started page up here: https://github.com/jcansdale/staticmocks
Closing as part of a general cleanup of issues. Please re-open if any action is required.
Hello,
Is there any way to implicitly implement the methods of substituted interfaces?
For example the following test current fails. Is there any way to make it pass without duplicating the
Returns
?It looks like the substituted class will look something like this:
Unfortunately this make the substituting of some COM interfaces particularly awkward.