Is there a way to check with NSubstitute that number of received calls falls within certain range?
I would like to do something like:
myMock.Received(r => r > 1 && r <= 5).MyMethod();
Alternatively, if I could get the exact number of received calls that would do the job as well. I am unit testing retries and timeouts and based on system load and other tests running number of retries can vary during unit test execution.
The NSubstitute API does not currently support this exactly (but it's a nice idea!).
There is a hacky-ish way of doing it using the unofficial .ReceivedCalls
extension:
var calls = myMock.ReceivedCalls()
.Count(x => x.GetMethodInfo().Name == nameof(myMock.MyMethod));
Assert.InRange(calls, 1, 5);
The better way to do this using a custom Quantity
from the NSubstitute.ReceivedExtensions
namespace:
// DISCLAIMER: draft code only. Review and test before using.
public class RangeQuantity : Quantity {
private readonly int min;
private readonly int maxInclusive;
public RangeQuantity(int min, int maxInclusive) {
// TODO: validate args, min < maxInclusive.
this.min = min;
this.maxInclusive = maxInclusive;
}
public override string Describe(string singularNoun, string pluralNoun) =>
$"between {min} and {maxInclusive} (inclusive) {((maxInclusive == 1) ? singularNoun : pluralNoun)}";
public override bool Matches<T>(IEnumerable<T> items) {
var count = items.Count();
return count >= min && count <= maxInclusive;
}
public override bool RequiresMoreThan<T>(IEnumerable<T> items) => items.Count() < min;
}
Then:
myMock.Received(new RangeQuantity(3,5)).MyMethod();
(Note you will need using NSubstitute.ReceivedExtensions;
for this.)