0

I faced with usage of NSubstitute inside business logic(outside of test classed):

var extension = Substitute.For<IExtension>();

I get used to utilization of NSubstitute inside test classes, when you need to mock some class(interface). But using NSubstitute outside of test classes confused me. Is it correct place for it? Is is correct to use NSubstitute like dependency injection container, that can create of instance of interface/class?

My concerns are that NSubstitute was designed to be used for tests. Performance inside tests is not very important thing, that is why it could be slow. Also, it relies on reflection, so it could not be very quick. But, is performance of NSubstitute poor, or is it ok?

Are there any other reasons, why NSubstitute or other mocking libraries should not be used outside of tests?

Anton
  • 9,682
  • 11
  • 38
  • 68
  • Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. – Nkosi Nov 15 '18 at 15:46
  • 1
    Just because it could be used in non-testing cases, does not mean that it **should** – Nkosi Nov 15 '18 at 15:48
  • @Nkosi yes, and I am trying to figure out why it shouldn't be used. Or it should be used and there are no problems with it. – Anton Nov 15 '18 at 15:51
  • The single answer is not opinion-based, but based on expert experience – Michael Freidgeim Feb 28 '19 at 21:06

1 Answers1

4

No, it is not generally good practice to use a mocking library in production code. (I'm going to use "generally" a lot here as I think any question on "good practice" will require a degree of generalisation. People may be able to come up with cases that work against this generalisation, but I think those cases will be the vast minority.)

Even without performance considerations, mocking libraries create test implementations for interfaces/classes. Test implementations generally support functions such as recording calls made and stubbing specific calls to return specific results. Generally when we have an interface or class for production code, it is to achieve some specific purpose, not the general purpose of recording calls and stubbing return values.

While it would be possible to provide a specific implementation for an interface using NSubstitute and to stub each call to execute production code logic, why not instead create a class with the required implementations instead?

This will generally have these advantages:

  • should be more succinct to implement (if not, consider switching to a better language! :D)
  • uses the native constructs of your programming language
  • should have better performance (removes levels of indirection required for mocking library)

For NSubstitute specifically there are some big reasons why you should never use it in production code. Because the library is designed for test code it uses some approaches that are unacceptable for production code:

  • It uses global state to support its syntax.
  • It abuses C#/VB syntax for the purpose of testing (can almost be considered a testing DSL). e.g. say sub.MyCall() returns an int. Stubbing a call like sub.MyCall().Returns(42) means we are calling int.Returns(42), which is now somehow going to influence a return value of a call outside of the int on which it is being called. This is quite different to how C#/VB generally works.
  • It requires virtual members for everything. This constraint is shared by many mocking libraries. For NSubstitute, you can get unpredictable results if you use it with non-virtual members. Unpredictability is not a nice thing to have for production code.
  • Tests are generally short-lived. NSubstitute (and probably other libraries) can make implementation decisions that rely on short-lived objects.
  • Tests show pass or failure for a particular case. This means if there is a problem in NSubstitute it can be immediately picked up while attempting to write and run a specific test. While a lot of effort goes into NSubstitute quality and reliability, the amount of work and scrutiny the C# compiler goes through is a completely different level. For production code, we want a very stable base to use as a foundation.

In summary: your programming language provides constructs designed and optimised for implementing logical interfaces. Your mocking library provides constructs designed and optimised for the much more limited task of providing test implementations of logical interfaces for use with testing code in isolation from its dependencies. Unless you have an ironclad reason as to why you would do the programming equivalent of digging a hole with a piece of paper instead of a shovel, I'd suggest using each tool for its intended purpose. :)

David Tchepak
  • 9,826
  • 2
  • 56
  • 68