Search code examples
unit-testingmockingmicrosoft-fakesnsubstitute

HOW to use MS Fakes shims with NSubstitute mocks?


This SO question addressed the "can", without showing "how". I am stuck at getting it up and running. Can any one provide an example? I tried

public abstract class MyClass
{
  public abstract Counter Counter { get; }
  public int abstract Foo(int n);
  public virtual int Foo(string s)
  {
    return Foo(Counter.Count(s));
  }          
}

I'd like to mock Foo(string s), which depends on the abstract property Counter. The reason I want to mock Foo(string s) is because I don't want to provide definitions for Counter and Foo(int n) since only Foo(string s) is used by the verification code.

Approach 1:

var sub = Substitute.For<MyClass>();
ShimMyClass.AllInstances.Func1Int32 = ... ; // alternate behavior for testing
VerifyLogic(sub);

Approach 2:

var sub = Substitute.For<MyClass>();
var shim = new ShimMyClass(sub)
{
   Func1Int32 = ... ; // alternate behavior for testing
};
VerifyLogic(shim.Instance);

Neither one worked, the original class code is called instead of the shim code. Thanks.


Solution

  • Assume the library that contains the class to be tested is Lib.

    namespace Lib
    {
    public interface Counter { int Count(string s); }
    
    public abstract class AbstractClass : AbstractParent
    {
        internal int Value { get; set; }
    
        public abstract int Foo(int x);
        public int Foo(string s) { return Foo(Counter.Count(s)); }
    }
    
    public abstract class AbstractParent
    {
        internal abstract Counter Counter { get; }
    }
    }
    

    Locate Lib in the References of the Test project. Select "Add Fakes Assembly".

        [TestMethod]
        public void AbstractMethod()
        {
            var instance = Substitute.For<AbstractClass>();
    
            using (ShimsContext.Create())
            {
                var instance = Substitute.For<AbstractClass>();
    
                Lib.Fakes.ShimAbstractClass.AllInstances.FooString =
                    (_, s) => 1999;
    
                Assert.AreEqual(1999, instance.Foo("hello"));
            }
        }