Creating shims

230 views
Skip to first unread message

testu...@gmail.com

unread,
Feb 11, 2014, 8:11:51 AM2/11/14
to nsubs...@googlegroups.com
Hello All,

Can NSubstitute create what are called shims in Microsoft terminology?

For example, consider:
// Code under test
class MyClass
{
  public string str1;
  
  public string MyMethod()
  {
    AnotherClass thatThing = new AnotherClass();
    string str2 =  thatThing.DoSomething(str1);
    // more code, which is what I am really trying to test
    return result;
  }
}

// Unit test code
MyClass myThing = new MyClass();
myThing.str1 = "TestInput"

// When thatThing.DoSomething is called with input "SampleInput"
// it should just return "SampleOutput" instead of calling the
// real AnotherClass:DoSomething(string)
//
// Apparently Microsoft Fakes can do this by (I think)
// ShimAnotherClass.AllInstances.DoSomething = ("SampleInput) => "SampleOutput";

string actualResult = myThing.MyMethod();
Assert.AreEqual("ExpectedResult", actualResult);

David Tchepak

unread,
Feb 11, 2014, 6:59:48 PM2/11/14
to nsubs...@googlegroups.com
No NSubstitute doesn't support ShimX.AllInstances.

The usual approach to mocking this with NSubstitute would be to inject AnotherClass (or a factory if it needs to be created per call), or pass it to MyMethod. In addition, NSubstitute requires the mocked members to be virtual. 

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 http://groups.google.com/group/nsubstitute.
For more options, visit https://groups.google.com/groups/opt_out.

testu...@gmail.com

unread,
Feb 11, 2014, 8:28:19 PM2/11/14
to nsubs...@googlegroups.com
Thanks, David. I have two questions:

1) You said that the mocked members had to be virtual. Is that true even if you are substituting an interface, as recommended in the docs? 

2) I have heard of dependency injection (which I assume is what you are talking about). I don't know anything about at this point, and I don't expect you to teach me here. However, can you *briefly* show how dependency injection will help me to mock AnotherClass? I *could* do something like (as you suggest):

// Unit test code
MyClass myThing = new MyClass();
myThing.str1 = "TestInput"
var thatThing = Substitute.For<AnotherClass>();
thatThing.DoSomething("SampleInput").Returns("SampleOutput");
string actualResult = myThing.MyMethod(thatThing);
Assert.AreEqual("ExpectedResult", actualResult);

but I would rather not if I can help it. thatThing is an implementation detail that does not need to be visible outside of MyClass::MyMethod. It would be in the argument list just to make it accessible to NSubstitute.

David Tchepak

unread,
Feb 11, 2014, 9:30:19 PM2/11/14
to nsubs...@googlegroups.com
1) Short version: interfaces are fine too. Better in fact!
Long version: 
Sorry I should have been clearer. NSub (and other DynamicProxy-based libraries) work by sub-classing the type you're substituting for, and overriding each member to change how it works. All members of an interface can be overridden, so that works best. Classes and abstract classes will also work provided the members are abstract or virtual (i.e. they can be overridden in the sub-class). You can also substitute for classes and abstract classes with a mix of virtual and non-virtual members, but NSubstitute will not know when the non-virtual members are called and so won't be able to change their behaviour (in fact, trying to set return values on non-virtuals can cause NSub to get confused and make your test fail).

2) Here are some examples of injecting the dependency into the code being tested: https://gist.github.com/dtchepak/8948799
Let me know if you would like explanations of any of them.

Hope this helps.
Regards,
David




--

testu...@gmail.com

unread,
Feb 12, 2014, 4:01:06 AM2/12/14
to nsubs...@googlegroups.com
2) Here are some examples of injecting the dependency into the code being tested: https://gist.github.com/dtchepak/8948799

Hello David,

Your examples are clear. Basically, they are variations of  the same theme - I must move the creation of thatThing from inside MyClass::MyMethod to the code that calls MyClass::MyMethod. I think that I will pass thatThing via the MyClass constructor. That way I don't clutter MyMethod's argument list. A shim would have been better, though. Is it possible that shims might be implemented in NSubstitute one day?

David Tchepak

unread,
Feb 12, 2014, 4:34:26 AM2/12/14
to nsubs...@googlegroups.com
It's very unlikely - NSubstitute isn't really designed for that. MS Fakes or something like TypeMock or JustMock are better bets if you need very advanced interception capabilities like this.





--
Reply all
Reply to author
Forward
0 new messages