I’m trying to test some TPL dataflow code and run into what looks like a covariance issue with NSubstitue param matching. It is asserting:
Expected to receive exactly 1 call matching:
Subscribe("987123", any ITargetBlock`1)
Actually received 1 matching call:
Subscribe("987123", ActionBlock<ChainLinkFakeData>)
From a matcher of:
childFakeSubscriptionSource
.Received(1)
.Subscribe(
Arg.Is<string>("987123"),
Arg.Any<ITargetBlock<ChainLinkFakeData>>());
So the stumbling block appears to be that it isn’t covariant matching ITargetBlock to the implementing class ActionBlock.
Is there a way to do this without explicitly matching to ActionBlock, or is it just a current limitation of NSubstitute?
edit: for everyones convenience, this is the class signature of ActionBlock. I think this is enough to see the covariance issue without pulling in a tonne of interfaces etc.
public sealed class ActionBlock<TInput> : ITargetBlock<TInput>, IDataflowBlock
The nub of the issue is that through covariance, ITargetBlock<T> should match an ActionBlock<T>. The arg matchers Arg.Any<ITargetBlock<ChainLinkFakeData>>() in NSubstitute don’t seem to?
The easy work around is Arg.Any<ActionBlock<ChainLinkFakeData>>() but that requires knowledge of the subject under tests implementation.
In terms of simpler example, I haven’t tested this, but I expect that there would be similar probs with IEnumerable<T> not matching List<T>.
This was a bug in NSubstitute, which should be fixed as of v1.4.0. (See original issue)