NSubstitute.Analyzers icon indicating copy to clipboard operation
NSubstitute.Analyzers copied to clipboard

Non-substitutable (non-virtual) member are sometimes still substitutable in extension methods

Open rklec opened this issue 2 years ago • 7 comments

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:

using NSubstitute;
using NUnit.Framework;

namespace Test
{
    class TestClass
    {
        [Test]
        public void NSubstituteNonVirtualTest_NS1001()
        {
            var thing = Substitute.For<ISomeThing>();

            thing.DoSomething();

            thing.Received(1).DoSomething(); // NS1001 error here
        }

        [Test]
        public void NSubstituteNonVirtualTest_NS1000()
        {
            var thing = Substitute.For<ISomeThing>();
            var otherThing = new Somethingelse();
            thing.GetModel<Somethingelse>(thing).Returns(otherThing); // NS1000 error here

            var result = thing.GetModel<Somethingelse>(thing);

            Assert.AreSame(result, otherThing);
        }
    }

    public class Something : ISomeThing
    {
        public Somethingelse Model { get; set; }
    }


    public class Somethingelse
    {
    }

    public interface ISomeThing
    {
        public Somethingelse Model { get; set; }
    }

    public interface ISomeThingelse
    {
    }
    
    public static class TestExtension
    {

        public static T DoSomething<T>(this T ownThing) where T : class, ISomeThing =>
            ownThing;

        public static Somethingelse GetModel<T>(this ISomeThing _, ISomeThing someThing)
        {
            var model = someThing.Model;

            return model;
        }
    }
}

Warnings

grafik grafik

System

DotNet Core 3.1

<TargetFramework>netcoreapp3.1</TargetFramework>
<!-- ... -->
<Nullable>enable</Nullable>

Dependencies:

		<PackageReference Include="NSubstitute" Version="4.2.2" />
		<PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.14" />

rklec avatar Sep 08 '21 10:09 rklec