Partial substitution on interface with concrete implementation (like composition)

40 views
Skip to first unread message

Dheerendra Rathor

unread,
Feb 5, 2019, 4:34:52 PM2/5/19
to NSubstitute
I've an interface which implements two interfaces, and a class implementing one of those interfaces

interface IA : IB, IC {
}

class BImpl : IB {
   
...
}

Is it possible to mock IA in a way that all calls which are defined in IB lands to object of BImpl while calls to methods in IC are mocked.

Something like:
var b = new BImpl();

var iaMock = Substitute.For<IA>(b); // or Substitute.For<IB, IC>(b)

iaMock
.MethodDefinedInIb(); // This should call b.MethodDefinedInIb();

iaMock
.MethodDefinedInIc().Returns("blah"); // This is calling generated mock implementation

Thanks

David Tchepak

unread,
Feb 5, 2019, 6:16:16 PM2/5/19
to nsubs...@googlegroups.com
Hello,

NSubstitute does not support saying "forward every call from `IB` to this instance of `BImpl`", but you can do this on a per method basis.

The snippet below uses NSubstitute 4.0:

    public interface IC {
        int GetInt(string s);
    }
    public interface IB {
        string GetString(string s);
    }
    public interface IA : IB, IC { }

    public class BImpl : IB {
        public virtual string GetString(string s) {
            return $"{s}!";
        }
    }
    public class UnitTest1 {
        [Fact]
        public void Partial() {
            var sub = Substitute.For<IA, BImpl>();

            // Method on IB / BImpl should call base implementation:
            sub.When(x => x.GetString(Arg.Any<string>())).CallBase();
            // Stub method on IC:
            sub.GetInt("hi").Returns(42);

            Assert.Equal("hi!", sub.GetString("hi"));
            Assert.Equal(42, sub.GetInt("hi"));
        }
    }

A bit more clumsy, but probably more obvious, is using `Returns` to forward to a real instance:

        [Fact]
        public void ForwardSpecificCalls() {
            var b = new BImpl();
            var sub = Substitute.For<IA>();
            sub.GetString("").ReturnsForAnyArgs(x => b.GetString(x.Arg<string>()));
            sub.GetInt("hi").Returns(42);

            Assert.Equal("hi!", sub.GetString("hi"));
            Assert.Equal(42, sub.GetInt("hi"));
        }


Hope this helps.
Regards,
David



--
You received this message because you are subscribed to the Google Groups "NSubstitute" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nsubstitute...@googlegroups.com.
To post to this group, send email to nsubs...@googlegroups.com.
Visit this group at https://groups.google.com/group/nsubstitute.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages