A friendly substitute for .NET mocking frameworks.
Перейти к файлу
Scott Bilas d4be72c6f7 Abandoning project in favor of our new NSubstitute.Elevated under dev 2018-08-08 09:26:13 +02:00
Build .gitattributes eol (#11) 2017-10-25 09:25:04 +02:00
Source Merge branch 'master' into VisitorPatternRevisit 2017-10-25 07:13:05 -05:00
ThirdParty merge upstream 2017-05-29 09:33:41 +02:00
.editorconfig Repo and editor config files for nice formatting 2016-06-09 13:35:02 +02:00
.gitattributes .gitattributes eol (#11) 2017-10-25 09:25:04 +02:00
.gitignore merge upstream 2017-05-29 09:33:41 +02:00
.hgeol Repo and editor config files for nice formatting 2016-06-09 13:35:02 +02:00
.repoconfig Turn on formatting 2017-05-27 11:04:40 +02:00
.travis.yml Update installation of OpenSSL following the https://www.microsoft.com/net/core#macos 2016-11-23 10:57:33 +02:00
BreakingChanges.txt Releasing 1.10.0 2016-03-30 16:29:03 +11:00
CHANGELOG.txt Fix changelog typo. 2017-04-25 11:27:26 +10:00
Gemfile
Gemfile.lock Updated Gemfile.lock after bundler update 2017-04-22 11:03:57 +10:00
LICENSE.txt
NSubstitute.sublime-project implement a test to ensure the fody injection basics are working 2016-07-25 17:02:06 +02:00
README.markdown Abandoning project in favor of our new NSubstitute.Elevated under dev 2018-08-08 09:26:13 +02:00
acknowledgements.markdown Removed rake build 2015-09-28 11:06:51 +10:00
appveyor.yml Add CI scripts 2016-08-07 11:06:51 +10:00
build.bat Repo and editor config files for nice formatting 2016-06-09 13:35:02 +02:00
build.fsx Updating build script to netstandard1.3 (was 1.5) 2017-04-25 10:43:10 +10:00
build.sh Removed rake build 2015-09-28 11:06:51 +10:00
global.json Fix AppVeyor CI 2017-04-03 12:05:01 +03:00
update-fake.bat Repo and editor config files for nice formatting 2016-06-09 13:35:02 +02:00
update-fake.sh

README.markdown

DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE

:D

I realized that we were continuing on the approach we took at Hackweek, which was intended to just get stuff working fast, but was not actually the right way to do things. We were forking NSubstitute and hacking at it, patching 'self' with Fody, using an overcomplicated patch mechanism, and much more.

This project is hereby abandoned in favor of https://github.com/Unity-Technologies/NSubstitute.Elevated.

DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE DO NOT USE

NSubstitute

Build status Travis Build Status

Visit the NSubstitute website for more information.

What is it?

NSubstitute is designed as a friendly substitute for .NET mocking libraries.

It is an attempt to satisfy our craving for a mocking library with a succinct syntax that helps us keep the focus on the intention of our tests, rather than on the configuration of our test doubles. We've tried to make the most frequently required operations obvious and easy to use, keeping less usual scenarios discoverable and accessible, and all the while maintaining as much natural language as possible.

Perfect for those new to testing, and for others who would just like to to get their tests written with less noise and fewer lambdas.

Getting help

If you have questions or feedback on NSubstitute, head on over to the NSubstitute discussion group.

Basic use

Let's say we have a basic calculator interface:

public interface ICalculator
{
    int Add(int a, int b);
    string Mode { get; set; }
    event Action PoweringUp;
}

We can ask NSubstitute to create a substitute instance for this type. We could ask for a stub, mock, fake, spy, test double etc., but why bother when we just want to substitute an instance we have some control over?

_calculator = Substitute.For<ICalculator>();

Now we can tell our substitute to return a value for a call:

_calculator.Add(1, 2).Returns(3);
Assert.That(_calculator.Add(1, 2), Is.EqualTo(3));

We can check that our substitute received a call, and did not receive others:

_calculator.Add(1, 2);
_calculator.Received().Add(1, 2);
_calculator.DidNotReceive().Add(5, 7);

If our Received() assertion fails, NSubstitute tries to give us some help as to what the problem might be:

NSubstitute.Exceptions.ReceivedCallsException : Expected to receive a call matching:
    Add(1, 2)
Actually received no matching calls.
Received 2 non-matching calls (non-matching arguments indicated with '*' characters):
    Add(1, *5*)
    Add(*4*, *7*)

We can also work with properties using the Returns syntax we use for methods, or just stick with plain old property setters (for read/write properties):

_calculator.Mode.Returns("DEC");
Assert.That(_calculator.Mode, Is.EqualTo("DEC"));

_calculator.Mode = "HEX";
Assert.That(_calculator.Mode, Is.EqualTo("HEX"));

NSubstitute supports argument matching for setting return values and asserting a call was received:

_calculator.Add(10, -5);
_calculator.Received().Add(10, Arg.Any<int>());
_calculator.Received().Add(10, Arg.Is<int>(x => x < 0));

We can use argument matching as well as passing a function to Returns() to get some more behaviour out of our substitute (possibly too much, but that's your call):

_calculator
   .Add(Arg.Any<int>(), Arg.Any<int>())
   .Returns(x => (int)x[0] + (int)x[1]);
Assert.That(_calculator.Add(5, 10), Is.EqualTo(15));

Returns() can also be called with multiple arguments to set up a sequence of return values.

_calculator.Mode.Returns("HEX", "DEC", "BIN");
Assert.That(_calculator.Mode, Is.EqualTo("HEX"));
Assert.That(_calculator.Mode, Is.EqualTo("DEC"));
Assert.That(_calculator.Mode, Is.EqualTo("BIN"));

Finally, we can raise events on our substitutes (unfortunately C# dramatically restricts the extent to which this syntax can be cleaned up):

bool eventWasRaised = false;
_calculator.PoweringUp += () => eventWasRaised = true;

_calculator.PoweringUp += Raise.Event<Action>();
Assert.That(eventWasRaised);

Building

If you have Visual Studio 2008, 2010, 2012, 2013, or 2015 you should be able to compile NSubstitute and run the unit tests using the NUnit GUI or console test runner (see the ThirdParty directory). Note that some tests are marked [Pending] and are not meant to pass at present, so it is a good idea to exclude tests in the Pending category from test runs. To do full builds you'll also need Ruby, as the jekyll gem is used to generate the website.