Skip to content

Commit 9cae120

Browse files
committed
add examples for ThrowsAsync, Arg.AnyType, ForTypeForwardingTo
1 parent 4121865 commit 9cae120

4 files changed

Lines changed: 89 additions & 2 deletions

File tree

nsubstitute/1-Tutorial.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,5 +360,63 @@ public void PerformingActionsWithArguments()
360360
}
361361
#endregion
362362
#endregion
363+
364+
#region New in NSubstitute 4+/5+
365+
[Test]
366+
public void ThrowsAsync_ForAsyncMethods()
367+
{
368+
// ThrowsAsync: throw exceptions from async methods (added in v4.4)
369+
var sub = Substitute.For<ICalculator>();
370+
371+
sub.AddAsync(1, 1).ThrowsAsync(new InvalidOperationException("Async failure"));
372+
373+
Assert.ThrowsAsync<InvalidOperationException>(async () => await sub.AddAsync(1, 1));
374+
375+
// Also works with ThrowsAsync<T>
376+
sub.AddAsync(2, 2).ThrowsAsync<ArgumentException>();
377+
Assert.ThrowsAsync<ArgumentException>(async () => await sub.AddAsync(2, 2));
378+
}
379+
380+
[Test]
381+
public void ArgAnyType_VerifyGenericCalls()
382+
{
383+
// Arg.AnyType: match any generic type parameter (added in v5.1)
384+
// Useful for verifying calls to generic methods regardless of type argument
385+
var sub = Substitute.For<ICalculator>();
386+
387+
sub.Store("a", 123);
388+
sub.Store("b", "hello");
389+
sub.Store("c", 3.14);
390+
391+
// Without Arg.AnyType, you'd need to verify each type separately:
392+
sub.Received().Store("a", 123);
393+
sub.Received().Store("b", "hello");
394+
sub.Received().Store("c", 3.14);
395+
396+
// With Arg.AnyType, verify all Store calls regardless of T
397+
sub.Received(3).Store(Arg.Any<string>(), Arg.Any<Arg.AnyType>());
398+
}
399+
400+
[Test]
401+
public void ForTypeForwardingTo_TestSpy()
402+
{
403+
// Test spy: forward calls to a real implementation (added in v5.3)
404+
// Useful when you want to verify calls but still execute real logic
405+
var realCalculator = new Calculator();
406+
var spy = Substitute.ForTypeForwardingTo<ICalculator, Calculator>();
407+
408+
// Calls go to real implementation
409+
int result = spy.Add(2, 3);
410+
Assert.That(result, Is.EqualTo(5)); // Real calculation
411+
412+
// But we can still verify calls
413+
spy.Received().Add(2, 3);
414+
415+
// And override specific methods
416+
spy.Add(10, 10).Returns(999);
417+
Assert.That(spy.Add(10, 10), Is.EqualTo(999)); // Overridden
418+
Assert.That(spy.Add(5, 5), Is.EqualTo(10)); // Still real
419+
}
420+
#endregion
363421
}
364422
}

nsubstitute/2-Moq-Comparison.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,5 +125,19 @@ public void Verification()
125125
// Properties
126126
var requiredAssignmentForCompiler = nsub.DidNotReceive().Mode;
127127
}
128+
129+
[Test]
130+
public void ThrowsAsync_Comparison()
131+
{
132+
// Moq
133+
var moq = new Mock<ICalculator>();
134+
moq.Setup(calc => calc.AddAsync(1, 1)).ThrowsAsync(new InvalidOperationException());
135+
Assert.ThrowsAsync<InvalidOperationException>(async () => await moq.Object.AddAsync(1, 1));
136+
137+
// NSubstitute
138+
var nsub = Substitute.For<ICalculator>();
139+
nsub.AddAsync(1, 1).ThrowsAsync(new InvalidOperationException());
140+
Assert.ThrowsAsync<InvalidOperationException>(async () => await nsub.AddAsync(1, 1));
141+
}
128142
}
129143
}

nsubstitute/Calculator.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ public class Calculator : ICalculator
44
{
55
public Calculator()
66
{
7-
87
}
98

109
public Calculator(int @base)
1110
{
12-
1311
}
1412

1513
public virtual int Add(int a, int b)
@@ -29,5 +27,15 @@ public void SetMode(string mode)
2927
{
3028
Mode = mode;
3129
}
30+
31+
public virtual async Task<int> AddAsync(int a, int b)
32+
{
33+
await Task.Delay(10);
34+
return a + b;
35+
}
36+
37+
public virtual T GetValue<T>(string key) => default!;
38+
39+
public virtual void Store<T>(string key, T value) { }
3240
}
3341
}

nsubstitute/ICalculator.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,12 @@ public interface ICalculator
66
int Divide(int n, int divisor, out float remainder);
77
string Mode { get; set; }
88
void SetMode(string mode);
9+
10+
// Added for async examples
11+
Task<int> AddAsync(int a, int b);
12+
13+
// Added for generic matching examples
14+
T GetValue<T>(string key);
15+
void Store<T>(string key, T value);
916
}
1017
}

0 commit comments

Comments
 (0)