SlideShare a Scribd company logo
Introduction to
NSubstitute
Agenda
 Test double and its Types
 Test Driven Development
 Introduction to NSubstitute
 Getting started
 Creating a substitute & Setting a return value
 Return for specific args, return for any args & return from a
function
 Multiple return values
 Replacing return values
 Checking received calls & Clearing received calls
 Argument matchers
 Void calls and When..Do
Cont..
 Throwing exceptions
 Raising events
 Auto and recursive mocks
 Setting out and ref args
 Checking call order
 Partial subs
 Advantage of NSubstitute
 Alternatives
 Q & A
Test double and its types
 “Test Double” is a generic term for any case where you replace
a production object for testing purposes.
 Test double types as listed below,
◦ Stub (used for providing the tested code with "indirect input")
◦ Mock (used for verifying "indirect output" of the tested code,
by first defining the expectations before the tested code is
executed)
◦ Spies (Are stubs that also record some information based on
how they were called. One form of this might be an email
service that records how many messages it was sent)
◦ Fake object (used as a simpler implementation, e.g. using an
in-memory database in the tests instead of doing real
database access)
◦ Dummy object (used when a parameter is needed for the
tested method but without actually needing to use the
parameter)
Test Driven Development
 TDD is an evolutionary approach to software development,
where you write a test cases first then you write just enough
production code to fulfill that test cases to pass and then
refactor the code.
 The result of using this practice is a comprehensive suite of
unit tests that can be run at any time to provide feedback that
the software is still working.
Introduction to NSubstitute
 NSubstitute is a friendly substitute for .NET mocking
frameworks. It has a simple, succinct syntax to help
developers write clearer tests.
 NSubstitute is designed for Arrange-Act-Assert (AAA) testing
and with Test Driven Development (TDD) in mind.
 It’s a open source framework.
 Latest version is 1.8.1.
Getting started
 The easiest way to get started is to reference NSubstitute
from your test project using the Nsubstitute NuGet package
via NuGet.
 Alternatively you can download NSubstitute and add a
reference to the NSubstitute.dll file included in the download
into your test project.
Creating a substitute & Setting a
return value
 The basic syntax for creating a substitute is:
var logSub = Substitute.For<ISomeInterface>();
Warning: Substituting for classes can have some nasty side-
effects. For starters, NSubstitute can only work with virtual
members of the class, so any non-virtual code in the class will
actually execute! If possible, stick to substituting interfaces.
 Return value can be set for a method or property.
var calculator = Substitute.For<ICalculator>();
calculator.Add(1, 2).Returns(3);
calculator.Mode.Returns("DEC");
Return for specific args, Return
for any args & Return from a
function
 Return for specific args
Return values can be configured for different combinations of
arguments passed to calls using argument matchers.
//Return when first arg is anything and second arg is 5:
calculator.Add(Arg.Any<int>(), 5).Returns(10);
Assert.AreEqual(10, calculator.Add(123, 5));
 Return for any args
A call can be configured to return a value regardless of the
arguments passed using the ReturnsForAnyArgs() extension
method.
//Return 100 regardless for the argument passed:
calculator.Add(1, 2).ReturnsForAnyArgs(100);
Assert.AreEqual(calculator.Add(1, 2), 100);
Assert.AreEqual(calculator.Add(-7, 15), 100);
 Return from a function
The return value for a call to a property or method can be set
to
the result of a function. This allows more complex logic to be
put
into the substitute. Although this is normally a bad practice,
there
are some situations in which it is useful.
public interface IFoo {
string Bar(int a, string b);
}
var foo = Substitute.For<IFoo>();
foo.Bar(0, "").ReturnsForAnyArgs(x => "Hello " +
x.Arg<string>());
Assert.That(foo.Bar(1, "World"), Is.EqualTo("Hello
World"));
Multiple return values
 A call can also be configured to return a different value over
multiple calls.
var calculator = Substitute.For<ICalculator>();
calculator.Mode.Returns("DEC", "HEX", "BIN");
Assert.AreEqual("DEC", calculator.Mode);
Assert.AreEqual("HEX", calculator.Mode);
Assert.AreEqual("BIN", calculator.Mode);
Replacing return values
 The return value for a method or property can be set as many
times as required. Only the most recently set value will be
returned.
calculator.Mode.Returns("DEC,HEX,OCT");
calculator.Mode.Returns(x => "???");
calculator.Mode.Returns("HEX");
calculator.Mode.Returns("BIN");
Assert.AreEqual(calculator.Mode, "BIN");
Checking received calls &
Clearing received calls
 Checking received calls
In some cases (particularly for void methods) it is useful to
check that a specific call has been received by a substitute.
This can be checked using the Received() extension method,
followed by the call being checked. There is DidNotReceive()
method to check if call is not recieved.
public class SomethingThatNeedsACommand
{
ICommand command;
public SomethingThatNeedsACommand(ICommand command) {
this.command = command; }
public void DoSomething() { command.Execute(); }
public void DontDoAnything() { }
}
[TestMethod]
public void Should_execute_command()
{
//Arrange
var command = Substitute.For<ICommand>();
var something = new
SomethingThatNeedsACommand(command);
//Act
something.DoSomething();
//Assert
command.Received().Execute();
}
 Clearing received calls
A substitute can forget all the calls previously made to it using
the ClearReceivedCalls() extension method.
Argument matchers
 Argument matchers can be used when setting return values
and when checking received calls. They provide a way to
specify a call or group of calls, so that a return value can be
set for all matching calls, or to check a matching call has
been receieved.
 Ignoring arguments
calculator.Add(Arg.Any<int>(), 5).Returns(7);
 Conditionally matching an argument
calculator.Received().Add(1, Arg.Is<int>(x => x < 0));
 Matching a specific argument
calculator.Add(0, 42);
Void calls and When..Do
 Returns() can be used to get callbacks for members that return a
value, but for void members we need a different technique, because
we can’t call a method on a void return. For these cases we can use
the When..Do syntax.
public interface IFoo
{
void SayHello(string to);
}
[TestMethod]
public void SayHello()
{
var counter = 0;
var foo = Substitute.For<IFoo>();
foo.When(x => x.SayHello("World"))
.Do(x => counter++);
foo.SayHello("World");
foo.SayHello("World");
Assert.AreEqual(2, counter);
}
Throwing exceptions
 Callbacks can be used to throw exceptions when a member
is called.
var calculator = Substitute.For<ICalculator>();
//For non-voids:
calculator.Add(-1, -1).Returns(x => { throw new Exception();
});
//For voids and non-voids:
calculator.When(x => x.Add(-2, -2))
.Do(x => { throw new Exception(); });
//Both calls will now throw.
Assert.Throws<Exception>(() => calculator.Add(-1, -1));
Assert.Throws<Exception>(() => calculator.Add(-2, -2));
Raising events
 Events are “interesting” creatures in the .NET world, as you
can’t pass around references to them like you can with other
members.
 Instead, you can only add or remove handlers to events
public interface IEngine
{
event EventHandler Idling;
event EventHandler<LowFuelWarningEventArgs> LowFuelWarning;
event Action<int> RevvedAt;
}
public class LowFuelWarningEventArgs : EventArgs
{
public int PercentLeft { get; private set; }
public LowFuelWarningEventArgs(int percentLeft)
{
PercentLeft = percentLeft;
}
Cont..
int numberOfEvents,revvedAt = 0;
var engine = Substitute.For<IEngine>();
engine.LowFuelWarning += (sender, args) => numberOfEvents++;
//Raise event with specific args, any sender:
engine.LowFuelWarning += Raise.EventWith(new
LowFuelWarningEventArgs(10));
//Raise event with specific args and sender:
engine.LowFuelWarning += Raise.EventWith(new object(), new
LowFuelWarningEventArgs(10));
engine.RevvedAt += rpm => revvedAt = rpm;
engine.RevvedAt += Raise.Event<Action<int>>(123);
Assert.AreEqual(2, numberOfEvents);
Assert.AreEqual(123, revvedAt);
Auto and recursive mocks
 Any properties or methods that return an interface, delegate,
or purely virtual class* will automatically return substitutes
themselves. This is commonly referred to as recursive
mocking.
 It is useful because you can avoid explicitly creating each
substitute, which means less code.
public interface IContext
{
IRequest CurrentRequest { get; }
}
public interface IRequest
{
IIdentity Identity { get; }
IIdentity NewIdentity(string name);
}
public interface IIdentity
{
string Name { get; }
string[] Roles();
}
var context = Substitute.For<IContext>();
context.CurrentRequest.Identity.Name.Returns("My pet fish Eric");
Assert.AreEqual("My pet fish Eric",
context.CurrentRequest.Identity.Name);
Here CurrentRequest is automatically going to return a
substitute for IRequest, and the IRequest substitute will
automatically return a substitute for IIdentity.
Cont..
Setting out and ref args
 Out and ref arguments can be set using a Returns() callback,
or using When..Do.
public interface ILookup
{
bool TryLookup(string key, out string value);
}
For the interface above we can configure the return value and
set the output of the second argument
//Arrange
var value = "";
var lookup = Substitute.For<ILookup>();
lookup
.TryLookup("hello", out value)
.Returns(x =>
{
x[1] = "world!";
return true;
});
//Act
var result = lookup.TryLookup("hello", out value);
//Assert
Assert.True(result);
Assert.AreEqual(value, "world!");
Cont..
Checking call order
 Sometimes calls need to be made in a specific order.
Depending on the timing of calls like this is known as
temporal coupling.
 Ideally we’d change our design to remove this coupling, but
for times when we can’t NSubstitute lets us resort to asserting
the order of calls.
[Test]
public void TestCommandRunWhileConnectionIsOpen()
{
var connection = Substitute.For<IConnection>();
var command = Substitute.For<ICommand>();
var subject = new Controller(connection, command);
subject.DoStuff();
Received.InOrder(() =>{
connection.Open();
command.Run(connection);
connection.Close();});
}
Partial Stubs
 Partial substitutes allow us to create an object that acts like a
real instance of a class, and selectively substitute for specific
parts of that object.
 This is useful for when we need a substitute to have real
behavior except for a single method that we want to replace, or
when we just want to spy on what calls are being made.
public class SummingReader
{
public virtual int Read(string path)
{
var s = ReadFile(path);
return s.Split(',').Select(int.Parse).Sum();
}
public virtual string ReadFile(string path) { return "the result
of reading the file here"; }
}
Cont…
[Test]
public void ShouldSumAllNumbersInFile()
{
var reader = Substitute.ForPartsOf<SummingReader>();
reader.ReadFile(Arg.Is("foo.txt")).Returns("1,2,3,4,5");
var result = reader.Read("foo.txt");
Assert.That(result, Is.EqualTo(15));
}
Advantages of NSubstitute
 It works really well with TDD.
 You do not have to pay the ‘lambda tax’ which is present in
RhinoMocks, Moq and Fake it easy.
 NSubstitute uses c# language features in a really clever way
to simplify usage.
◦ This results in each interaction requiring less code and
being easier to read.
Alternatives
 Moq
 JustMock
 FakeItEasy
 EasyMock.NET
 NMock 3
 Rhino Mocks
Q & A
Thank you

More Related Content

PDF
Principles Of Chaos Engineering - Chaos Engineering Hamburg
PPTX
Angular interview questions
PPTX
API Testing.pptx
PPT
Angular Introduction By Surekha Gadkari
PDF
Documenting your REST API with Swagger - JOIN 2014
PPT
TestLink introduction
PDF
Hexagonal architecture message-oriented software design
PPTX
GraphQL Security
Principles Of Chaos Engineering - Chaos Engineering Hamburg
Angular interview questions
API Testing.pptx
Angular Introduction By Surekha Gadkari
Documenting your REST API with Swagger - JOIN 2014
TestLink introduction
Hexagonal architecture message-oriented software design
GraphQL Security

What's hot (20)

PDF
What is API - Understanding API Simplified
PDF
Angular
PDF
Test Driven Development (TDD)
ODP
Using Mockito
PPTX
What Is Express JS?
PDF
Biml for Beginners - Generating SSIS Packages with BimlScript (SQLSaturday Ex...
PPTX
Unit testing JavaScript: Jasmine & karma intro
PPTX
Meetup angular http client
PDF
Introduzione ad angular 7/8
PDF
Socket.IO
PPTX
Manual Testing tutorials and Interview Questions.pptx
PPTX
Sharing Data Between Angular Components
PDF
Unit Testing in Angular
PPTX
PDF
Manual Testing
PPTX
Getting Started with API Security Testing
PDF
XSS Magic tricks
PPTX
Angular 18 course for begineers and experienced
PPTX
Angular Basics.pptx
PDF
Context API in React
What is API - Understanding API Simplified
Angular
Test Driven Development (TDD)
Using Mockito
What Is Express JS?
Biml for Beginners - Generating SSIS Packages with BimlScript (SQLSaturday Ex...
Unit testing JavaScript: Jasmine & karma intro
Meetup angular http client
Introduzione ad angular 7/8
Socket.IO
Manual Testing tutorials and Interview Questions.pptx
Sharing Data Between Angular Components
Unit Testing in Angular
Manual Testing
Getting Started with API Security Testing
XSS Magic tricks
Angular 18 course for begineers and experienced
Angular Basics.pptx
Context API in React
Ad

Similar to Introduction to nsubstitute (20)

PDF
Currying and Partial Function Application (PFA)
PDF
MT_01_unittest_python.pdf
PPT
Enumerable
ODP
Finagle and Java Service Framework at Pinterest
PDF
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
KEY
Unit testing en iOS @ MobileCon Galicia
PDF
Intro to Unit Testing in AngularJS
DOCX
PPTX
Rx workshop
PPT
Test driven development_for_php
PPTX
Function C++
PDF
JVM Mechanics: Understanding the JIT's Tricks
PPTX
Unit testing patterns for concurrent code
PPTX
Java fundamentals
PPTX
Fundamentals of functions in C program.pptx
PDF
JUnit Pioneer
PPTX
Flink Batch Processing and Iterations
PPT
Test Driven Development with PHPUnit
PPTX
EContent_11_2023_04_09_11_30_38_Unit_3_Objects_and_Classespptx__2023_03_20_12...
PPTX
LinkedIn TBC JavaScript 100: Functions
Currying and Partial Function Application (PFA)
MT_01_unittest_python.pdf
Enumerable
Finagle and Java Service Framework at Pinterest
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing en iOS @ MobileCon Galicia
Intro to Unit Testing in AngularJS
Rx workshop
Test driven development_for_php
Function C++
JVM Mechanics: Understanding the JIT's Tricks
Unit testing patterns for concurrent code
Java fundamentals
Fundamentals of functions in C program.pptx
JUnit Pioneer
Flink Batch Processing and Iterations
Test Driven Development with PHPUnit
EContent_11_2023_04_09_11_30_38_Unit_3_Objects_and_Classespptx__2023_03_20_12...
LinkedIn TBC JavaScript 100: Functions
Ad

Recently uploaded (20)

PPTX
MYSQL Presentation for SQL database connectivity
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Modernizing your data center with Dell and AMD
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Electronic commerce courselecture one. Pdf
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Approach and Philosophy of On baking technology
PPTX
Big Data Technologies - Introduction.pptx
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Chapter 3 Spatial Domain Image Processing.pdf
MYSQL Presentation for SQL database connectivity
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Advanced methodologies resolving dimensionality complications for autism neur...
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Network Security Unit 5.pdf for BCA BBA.
Understanding_Digital_Forensics_Presentation.pptx
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
The AUB Centre for AI in Media Proposal.docx
Modernizing your data center with Dell and AMD
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Electronic commerce courselecture one. Pdf
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Approach and Philosophy of On baking technology
Big Data Technologies - Introduction.pptx
“AI and Expert System Decision Support & Business Intelligence Systems”
Diabetes mellitus diagnosis method based random forest with bat algorithm
Chapter 3 Spatial Domain Image Processing.pdf

Introduction to nsubstitute

  • 2. Agenda  Test double and its Types  Test Driven Development  Introduction to NSubstitute  Getting started  Creating a substitute & Setting a return value  Return for specific args, return for any args & return from a function  Multiple return values  Replacing return values  Checking received calls & Clearing received calls  Argument matchers  Void calls and When..Do
  • 3. Cont..  Throwing exceptions  Raising events  Auto and recursive mocks  Setting out and ref args  Checking call order  Partial subs  Advantage of NSubstitute  Alternatives  Q & A
  • 4. Test double and its types  “Test Double” is a generic term for any case where you replace a production object for testing purposes.  Test double types as listed below, ◦ Stub (used for providing the tested code with "indirect input") ◦ Mock (used for verifying "indirect output" of the tested code, by first defining the expectations before the tested code is executed) ◦ Spies (Are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent) ◦ Fake object (used as a simpler implementation, e.g. using an in-memory database in the tests instead of doing real database access) ◦ Dummy object (used when a parameter is needed for the tested method but without actually needing to use the parameter)
  • 5. Test Driven Development  TDD is an evolutionary approach to software development, where you write a test cases first then you write just enough production code to fulfill that test cases to pass and then refactor the code.  The result of using this practice is a comprehensive suite of unit tests that can be run at any time to provide feedback that the software is still working.
  • 6. Introduction to NSubstitute  NSubstitute is a friendly substitute for .NET mocking frameworks. It has a simple, succinct syntax to help developers write clearer tests.  NSubstitute is designed for Arrange-Act-Assert (AAA) testing and with Test Driven Development (TDD) in mind.  It’s a open source framework.  Latest version is 1.8.1.
  • 7. Getting started  The easiest way to get started is to reference NSubstitute from your test project using the Nsubstitute NuGet package via NuGet.  Alternatively you can download NSubstitute and add a reference to the NSubstitute.dll file included in the download into your test project.
  • 8. Creating a substitute & Setting a return value  The basic syntax for creating a substitute is: var logSub = Substitute.For<ISomeInterface>(); Warning: Substituting for classes can have some nasty side- effects. For starters, NSubstitute can only work with virtual members of the class, so any non-virtual code in the class will actually execute! If possible, stick to substituting interfaces.  Return value can be set for a method or property. var calculator = Substitute.For<ICalculator>(); calculator.Add(1, 2).Returns(3); calculator.Mode.Returns("DEC");
  • 9. Return for specific args, Return for any args & Return from a function  Return for specific args Return values can be configured for different combinations of arguments passed to calls using argument matchers. //Return when first arg is anything and second arg is 5: calculator.Add(Arg.Any<int>(), 5).Returns(10); Assert.AreEqual(10, calculator.Add(123, 5));
  • 10.  Return for any args A call can be configured to return a value regardless of the arguments passed using the ReturnsForAnyArgs() extension method. //Return 100 regardless for the argument passed: calculator.Add(1, 2).ReturnsForAnyArgs(100); Assert.AreEqual(calculator.Add(1, 2), 100); Assert.AreEqual(calculator.Add(-7, 15), 100);
  • 11.  Return from a function The return value for a call to a property or method can be set to the result of a function. This allows more complex logic to be put into the substitute. Although this is normally a bad practice, there are some situations in which it is useful. public interface IFoo { string Bar(int a, string b); } var foo = Substitute.For<IFoo>(); foo.Bar(0, "").ReturnsForAnyArgs(x => "Hello " + x.Arg<string>()); Assert.That(foo.Bar(1, "World"), Is.EqualTo("Hello World"));
  • 12. Multiple return values  A call can also be configured to return a different value over multiple calls. var calculator = Substitute.For<ICalculator>(); calculator.Mode.Returns("DEC", "HEX", "BIN"); Assert.AreEqual("DEC", calculator.Mode); Assert.AreEqual("HEX", calculator.Mode); Assert.AreEqual("BIN", calculator.Mode);
  • 13. Replacing return values  The return value for a method or property can be set as many times as required. Only the most recently set value will be returned. calculator.Mode.Returns("DEC,HEX,OCT"); calculator.Mode.Returns(x => "???"); calculator.Mode.Returns("HEX"); calculator.Mode.Returns("BIN"); Assert.AreEqual(calculator.Mode, "BIN");
  • 14. Checking received calls & Clearing received calls  Checking received calls In some cases (particularly for void methods) it is useful to check that a specific call has been received by a substitute. This can be checked using the Received() extension method, followed by the call being checked. There is DidNotReceive() method to check if call is not recieved. public class SomethingThatNeedsACommand { ICommand command; public SomethingThatNeedsACommand(ICommand command) { this.command = command; } public void DoSomething() { command.Execute(); } public void DontDoAnything() { } }
  • 15. [TestMethod] public void Should_execute_command() { //Arrange var command = Substitute.For<ICommand>(); var something = new SomethingThatNeedsACommand(command); //Act something.DoSomething(); //Assert command.Received().Execute(); }  Clearing received calls A substitute can forget all the calls previously made to it using the ClearReceivedCalls() extension method.
  • 16. Argument matchers  Argument matchers can be used when setting return values and when checking received calls. They provide a way to specify a call or group of calls, so that a return value can be set for all matching calls, or to check a matching call has been receieved.  Ignoring arguments calculator.Add(Arg.Any<int>(), 5).Returns(7);  Conditionally matching an argument calculator.Received().Add(1, Arg.Is<int>(x => x < 0));  Matching a specific argument calculator.Add(0, 42);
  • 17. Void calls and When..Do  Returns() can be used to get callbacks for members that return a value, but for void members we need a different technique, because we can’t call a method on a void return. For these cases we can use the When..Do syntax. public interface IFoo { void SayHello(string to); } [TestMethod] public void SayHello() { var counter = 0; var foo = Substitute.For<IFoo>(); foo.When(x => x.SayHello("World")) .Do(x => counter++); foo.SayHello("World"); foo.SayHello("World"); Assert.AreEqual(2, counter); }
  • 18. Throwing exceptions  Callbacks can be used to throw exceptions when a member is called. var calculator = Substitute.For<ICalculator>(); //For non-voids: calculator.Add(-1, -1).Returns(x => { throw new Exception(); }); //For voids and non-voids: calculator.When(x => x.Add(-2, -2)) .Do(x => { throw new Exception(); }); //Both calls will now throw. Assert.Throws<Exception>(() => calculator.Add(-1, -1)); Assert.Throws<Exception>(() => calculator.Add(-2, -2));
  • 19. Raising events  Events are “interesting” creatures in the .NET world, as you can’t pass around references to them like you can with other members.  Instead, you can only add or remove handlers to events public interface IEngine { event EventHandler Idling; event EventHandler<LowFuelWarningEventArgs> LowFuelWarning; event Action<int> RevvedAt; } public class LowFuelWarningEventArgs : EventArgs { public int PercentLeft { get; private set; } public LowFuelWarningEventArgs(int percentLeft) { PercentLeft = percentLeft; }
  • 20. Cont.. int numberOfEvents,revvedAt = 0; var engine = Substitute.For<IEngine>(); engine.LowFuelWarning += (sender, args) => numberOfEvents++; //Raise event with specific args, any sender: engine.LowFuelWarning += Raise.EventWith(new LowFuelWarningEventArgs(10)); //Raise event with specific args and sender: engine.LowFuelWarning += Raise.EventWith(new object(), new LowFuelWarningEventArgs(10)); engine.RevvedAt += rpm => revvedAt = rpm; engine.RevvedAt += Raise.Event<Action<int>>(123); Assert.AreEqual(2, numberOfEvents); Assert.AreEqual(123, revvedAt);
  • 21. Auto and recursive mocks  Any properties or methods that return an interface, delegate, or purely virtual class* will automatically return substitutes themselves. This is commonly referred to as recursive mocking.  It is useful because you can avoid explicitly creating each substitute, which means less code. public interface IContext { IRequest CurrentRequest { get; } } public interface IRequest { IIdentity Identity { get; } IIdentity NewIdentity(string name); } public interface IIdentity { string Name { get; } string[] Roles(); }
  • 22. var context = Substitute.For<IContext>(); context.CurrentRequest.Identity.Name.Returns("My pet fish Eric"); Assert.AreEqual("My pet fish Eric", context.CurrentRequest.Identity.Name); Here CurrentRequest is automatically going to return a substitute for IRequest, and the IRequest substitute will automatically return a substitute for IIdentity. Cont..
  • 23. Setting out and ref args  Out and ref arguments can be set using a Returns() callback, or using When..Do. public interface ILookup { bool TryLookup(string key, out string value); } For the interface above we can configure the return value and set the output of the second argument
  • 24. //Arrange var value = ""; var lookup = Substitute.For<ILookup>(); lookup .TryLookup("hello", out value) .Returns(x => { x[1] = "world!"; return true; }); //Act var result = lookup.TryLookup("hello", out value); //Assert Assert.True(result); Assert.AreEqual(value, "world!"); Cont..
  • 25. Checking call order  Sometimes calls need to be made in a specific order. Depending on the timing of calls like this is known as temporal coupling.  Ideally we’d change our design to remove this coupling, but for times when we can’t NSubstitute lets us resort to asserting the order of calls. [Test] public void TestCommandRunWhileConnectionIsOpen() { var connection = Substitute.For<IConnection>(); var command = Substitute.For<ICommand>(); var subject = new Controller(connection, command); subject.DoStuff(); Received.InOrder(() =>{ connection.Open(); command.Run(connection); connection.Close();}); }
  • 26. Partial Stubs  Partial substitutes allow us to create an object that acts like a real instance of a class, and selectively substitute for specific parts of that object.  This is useful for when we need a substitute to have real behavior except for a single method that we want to replace, or when we just want to spy on what calls are being made. public class SummingReader { public virtual int Read(string path) { var s = ReadFile(path); return s.Split(',').Select(int.Parse).Sum(); } public virtual string ReadFile(string path) { return "the result of reading the file here"; } }
  • 27. Cont… [Test] public void ShouldSumAllNumbersInFile() { var reader = Substitute.ForPartsOf<SummingReader>(); reader.ReadFile(Arg.Is("foo.txt")).Returns("1,2,3,4,5"); var result = reader.Read("foo.txt"); Assert.That(result, Is.EqualTo(15)); }
  • 28. Advantages of NSubstitute  It works really well with TDD.  You do not have to pay the ‘lambda tax’ which is present in RhinoMocks, Moq and Fake it easy.  NSubstitute uses c# language features in a really clever way to simplify usage. ◦ This results in each interaction requiring less code and being easier to read.
  • 29. Alternatives  Moq  JustMock  FakeItEasy  EasyMock.NET  NMock 3  Rhino Mocks
  • 30. Q & A