Introduce substitute refactoring comes to NSubstitute.Analyzers

I am glad to announce the newest version of NSubstitute.Analyzers comes with “introduce substitute” refactoring, which allows you to automatically create substitutes for constructor arguments as fields or local variables. As an image is worth a thousand words here is a quick demo of C# version

and VisualBasic one

Introduce substitute refactoring comes to NSubstitute.Analyzers

Performance improvements in NSubstitute.Analyzers 1.0.11

1. Introduction

I am glad to announce that the latest release of NSubstitute.Analyzers (apart from some bugfixes) brings a lot of performance and memory usage improvements for most of the analyzers. The benchmark results shown below should give you enough information about the speed and memory consumption of the newest version of the library. If you are interested in actual changes behind these results please take a look at this pull request.

2. Benchmark comparision of NSubstitute.Analyzers.CSharp

AnalyzerMean (us)Error (us)StdDev (us)Gen 0Gen 1Allocated (KB)
CallInfoAnalyzer1,897.05.6465.2814136.718811.7188424.54
ConflictingArgumentAssignmentsAnalyzer554.21.0180.952433.20311.9531103.47
NonSubstitutableMemberAnalyzer2,466.99.3178.2596179.687515.6250560.33
NonSubstitutableMemberReceivedAnalyzer644.42.2801.903931.25006.835996.27
NonSubstitutableMemberWhenAnalyzer995.92.3201.937037.10947.8125116.74
ReEntrantSetupAnalyzer57,979.0196.824174.47942333.33337175.61
SubstituteAnalyzer1,960.48.1977.266689.843819.5313343.67
UnusedReceivedAnalyzer524.01.6711.563029.29691.953192.45
Benchmark results of NSubstitute.Analyzers.CSharp 1.0.11
AnalyzerMean (us)Error (us)StdDev (us)Gen 0Gen 1Allocated (KB)
CallInfoAnalyzer1,828.85.5994.963123.046911.7188379.78
ConflictingArgumentAssignmentsAnalyzer510.31.9731.84633.20311.9531102.76
NonSubstitutableMemberAnalyzer766.02.7982.33639.06258.7891122.27
NonSubstitutableMemberReceivedAnalyzer600.63.4113.19127.34385.859485.82
NonSubstitutableMemberWhenAnalyzer866.03.1442.94134.17979.7656107.87
ReEntrantSetupAnalyzer7,442.034.06731.866281.250015.6250870.18
SubstituteAnalyzer1,870.229.78727.86387.890623.4375346.09
UnusedReceivedAnalyzer482.11.7051.51125.87891.953180.96


3. Benchmark comparision of NSubstitute.Analyzers.VisualBasic

MethodMean (ms)Error (ms)StdDev (ms)Gen 0Gen 1Allocated (KB)
CallInfoAnalyzer3.4590.01370.0121156.250011.7188484.15
ConflictingArgumentAssignmentsAnalyzer1.2790.01030.008621.48441.953169.15
NonSubstitutableMemberAnalyzer1.9750.01080.009035.15637.8125108
NonSubstitutableMemberReceivedAnalyzer1.2870.00700.006513.67191.953147.46
NonSubstitutableMemberWhenAnalyzer1.5890.01030.009225.39065.859482.72
ReEntrantSetupAnalyzer54.1310.23200.19373600.000011139.45
SubstituteAnalyzer3.6150.01680.0149105.468823.4375393.13
UnusedReceivedAnalyzer1.3060.02580.052813.67191.953143.3
Benchmark results of NSubstitute.Analyzers.VisualBasic
1.0.11
AnalyzerMean (ms)Error (ms)StdDev (ms)Gen 0Gen 1Allocated (KB)
CallInfoAnalyzer3.7370.08780.1110152.343811.7188471.79
ConflictingArgumentAssignmentsAnalyzer1.4020.02660.028521.48441.953168.36
NonSubstitutableMemberAnalyzer1.5430.02640.024725.39065.859481
NonSubstitutableMemberReceivedAnalyzer1.2130.00510.004813.67191.953145.43
NonSubstitutableMemberWhenAnalyzer1.4750.00550.005127.34387.812585.25
ReEntrantSetupAnalyzer7.0440.02360.0209265.62507.8125837.14
SubstituteAnalyzer3.3330.09120.1186101.562523.4375377.16
UnusedReceivedAnalyzer1.1020.00670.006211.718840.24
Performance improvements in NSubstitute.Analyzers 1.0.11

NSubstitute – returning value from IEnumerable

I’ve been using NSubstitute combined with automocks for quite some time already, but recently I’ve encountered quite interesting situation. Let’s assume that we have the following class we need to write tests for

As mentioned before I wanted to test that class leveraging the concept of automocks. If you have never used them before, no worries, the idea is pretty simple. Instead of providing mock dependencies manually, you just generate them automatically. Once the dependencies are mocked you can retrieve and set them up if necessary. So in my case, I have to setup IEnumerable<IValidator<Price>> mock so that it yields some values. It can be achieved by mocking return values of GetEnumerator() method.

The entire test then can be written as

Everything looks good at that point, however if you run the tests, it will fail
FailedTest
That was quite surprising for me and I have to admit that at the beginning I thought it was a bug in NSubstitute.
However, if you looks closely at the implementation of the test, you will see that every time validator collection is enumerated, the same instance of the enumerator is used. As the enumerator keeps its state, the first enumeration (_innerValidators.Any()) will move a current element to the first position (which is the last position at the same time) so when I try to enumerate again (_innerValidators.All(validator => validator.IsValid(input)) enumeration will continue from the previous position and the iteration will end yielding no results. Fortunately, with NSubstitute you can configure the call so that it always returns a new value. The relevant code changes are shown below

Running the tests again will give us “green” result
Green

Source code for this post can be found here

NSubstitute – returning value from IEnumerable