NSubstitute to (dla tych co nie znają jeszcze) taki Moq na sterydach. Sytuacja wygląda tak, mamy klasę, która potrzebuje jakiś zależności, mniej więcej tak:

  public class SomeClass
  {
    public SomeClass(INeedSomeStuff stuff)
    {
        // .......
    }
  }

  public interface INeedSomeStuff
  {
     string DoSomeStuff(string param);
     void DoSomeOtherStuff();
  }

Możemy użyć moq i napisać:

var moq = new Mock<INeedSomeStuff>();
moq.Setup(m => m.DoSomeStuff("Hello")).Returns(r => "World");

INeedSomeStuff someStuff = moq.Object;
var someObj = new SomeClass(someStuff);

lub za pomocą NSubstitue napisać dokładnie to samo tak:

var someStuff = Substitute.For<INeedSomeStuff>();
someStuff.DoSomeStuff("Hello").Returns("World");
            
var someObj = new SomeClass(someStuff);

poza tym, że pozbywamy się lambd, to jeszcze nie mamy dodatkowego .Object o którym trzeba pamiętać, ot mamy zamiennik naszej klasy. Ale to nie wszystko, jest jeszcze lepiej, NSubstitute działa od razu, więc nie trzeba robić setupów w miejscach, gdzie czasem moq tego wymaga ale najlepsze to kwiatek na jaki się nadziałem przy przechodzeniu z Moq na NSubstitute. Jest kawałek kodu, który zwraca kolorki z zadanej palety, po kolej – ColorGenerator. Metoda GetColor() zwraca kolor z tablicy. Za każdym wywołaniem bierze następny kolor. Tyle teorii. Sytuacja taka, że trzeba to zamockować:

 _mockColorGenerator.Setup(x => x.GetColor()).Returns(_colors[0])
     .Callback(() => _mockColorGenerator.Setup(x => x.GetColor()).Returns(_colors[1])
     .Callback(() => _mockColorGenerator.Setup(x => x.GetColor()).Returns(_colors[2])
     .Callback(() => _mockColorGenerator.Setup(x => x.GetColor()).Returns(_colors[3]))));

Może, za pomocą moq można to napisać lepiej no ale jest (było) i działało. W NSubstitute można to zapisać tak:

_colorGenerator.GetColor().Returns(_colors[0], _colors[1], _colors[2], _colors[3]);

Efekt ten sam tylko 6 lambd mniej, 3 callbacki mniej, ogólniej wielokronie czytelniej.

P.S. NSubstitute jest na nugecie więc instalacja jest bezproblemowa, dodatkowo można używać równolegle z moq i małymi kroczkami wycinać tego ostatniego.