Skip to content

Commit 747cec7

Browse files
committed
docs: document repeating callback invocations (For)
1 parent f6e2ebe commit 747cec7

2 files changed

Lines changed: 72 additions & 18 deletions

File tree

Docs/pages/advanced-features/02-advanced-callback-features.md

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,53 @@
11
# Advanced callback features
22

3-
## Conditional callbacks
3+
## Conditional callbacks (`When`)
44

55
Execute callbacks conditionally based on the zero-based invocation counter using `.When()`:
66

77
```csharp
88
sut.SetupMock.Method.Dispense(It.Is("Dark"), It.IsAny<int>())
9-
.Do(() => Console.WriteLine("Called!"))
10-
.When(count => count >= 2); // The first two calls are skipped
9+
.Do(() => Console.WriteLine("Called!")).When(count => count >= 2); // The first two calls are skipped
1110
```
1211

13-
## Frequency control
12+
## Limit invocations (`Only`)
1413

15-
Control how many times a callback executes:
14+
Control after how many times a callback should no longer be executed:
1615

1716
```csharp
1817
// Execute up to 3 times
1918
sut.SetupMock.Method.Dispense(It.IsAny<string>(), It.IsAny<int>())
20-
.Do(() => Console.WriteLine("Up to 3 times"))
21-
.Only(3);
19+
.Do(() => Console.WriteLine("Up to 3 times")).Only(3);
2220

2321
// Executes the callback only once
22+
sut.SetupMock.Property.TotalDispensed
23+
.Throws(new Exception("This exception is thrown only once")).OnlyOnce();
24+
```
25+
26+
## Repeat invocations (`For`)
27+
28+
Control how many times a callback should be repeated:
29+
30+
```csharp
2431
sut.SetupMock.Method.Dispense(It.IsAny<string>(), It.IsAny<int>())
25-
.Do(() => Console.WriteLine("Only once"))
26-
.OnlyOnce();
32+
.Do(() => Console.WriteLine("First three times")).For(3)
33+
.Do(() => Console.WriteLine("Next three times")).For(3);
34+
35+
sut.SetupMock.Property.TotalDispensed
36+
.Returns(10).For(1)
37+
.Returns(20).For(2)
38+
.Returns(30).For(3);
39+
// Reads: 10, 20, 20, 30, 30, 30, 0, 0, 0, 0 …
40+
```
41+
42+
### Repeat `Forever`
43+
44+
If you have a sequence of callbacks, you can mark the last one to repeat indefinitely using `.Forever()` to avoid
45+
repeating the sequence from start:
46+
47+
```csharp
48+
sut.SetupMock.Method.Dispense(It.IsAny<string>(), It.IsAny<int>())
49+
.Returns(true).For(2) // Returns true the first two times
50+
.Returns(false).Forever(); // Then always returns false
2751
```
2852

2953
## Parallel callbacks
@@ -38,6 +62,9 @@ sut.SetupMock.Method.Dispense(It.IsAny<string>(), It.IsAny<int>())
3862
.Do(() => { Console.WriteLine("Runs every other iteration"); });
3963
```
4064

65+
**Note:**
66+
This only applies to callbacks defined via `Do`, not to the other setup callbacks like `Returns` or `Throws`.
67+
4168
## Invocation counter
4269

4370
Access the zero-based invocation counter in callbacks:

README.md

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -819,30 +819,54 @@ sut.VerifyMock.SetProtectedIndexer(It.Is(0), It.Is(42)).Once();
819819

820820
### Advanced callback features
821821

822-
#### Conditional callbacks
822+
#### Conditional callbacks (`When`)
823823

824824
Execute callbacks conditionally based on the zero-based invocation counter using `.When()`:
825825

826826
```csharp
827827
sut.SetupMock.Method.Dispense(It.Is("Dark"), It.IsAny<int>())
828-
.Do(() => Console.WriteLine("Called!"))
829-
.When(count => count >= 2); // The first two calls are skipped
828+
.Do(() => Console.WriteLine("Called!")).When(count => count >= 2); // The first two calls are skipped
830829
```
831830

832-
#### Frequency control
831+
#### Limit invocations (`Only`)
833832

834-
Control how many times a callback executes:
833+
Control after how many times a callback should no longer be executed:
835834

836835
```csharp
837836
// Execute up to 3 times
838837
sut.SetupMock.Method.Dispense(It.IsAny<string>(), It.IsAny<int>())
839-
.Do(() => Console.WriteLine("Up to 3 times"))
840-
.Only(3);
838+
.Do(() => Console.WriteLine("Up to 3 times")).Only(3);
841839

842840
// Executes the callback only once
841+
sut.SetupMock.Property.TotalDispensed
842+
.Throws(new Exception("This exception is thrown only once")).OnlyOnce();
843+
```
844+
845+
#### Repeat invocations (`For`)
846+
847+
Control how many times a callback should be repeated:
848+
849+
```csharp
850+
sut.SetupMock.Method.Dispense(It.IsAny<string>(), It.IsAny<int>())
851+
.Do(() => Console.WriteLine("First three times")).For(3)
852+
.Do(() => Console.WriteLine("Next three times")).For(3);
853+
854+
sut.SetupMock.Property.TotalDispensed
855+
.Returns(10).For(1)
856+
.Returns(20).For(2)
857+
.Returns(30).For(3);
858+
// Reads: 10, 20, 20, 30, 30, 30, 0, 0, 0, 0 …
859+
```
860+
861+
**Repeat `Forever`**
862+
863+
If you have a sequence of callbacks, you can mark the last one to repeat indefinitely using `.Forever()` to avoid
864+
repeating the sequence from start:
865+
866+
```csharp
843867
sut.SetupMock.Method.Dispense(It.IsAny<string>(), It.IsAny<int>())
844-
.Do(() => Console.WriteLine("Only once"))
845-
.OnlyOnce();
868+
.Returns(true).For(2) // Returns true the first two times
869+
.Returns(false).Forever(); // Then always returns false
846870
```
847871

848872
#### Parallel callbacks
@@ -857,6 +881,9 @@ sut.SetupMock.Method.Dispense(It.IsAny<string>(), It.IsAny<int>())
857881
.Do(() => { Console.WriteLine("Runs every other iteration"); });
858882
```
859883

884+
**Note:**
885+
This only applies to callbacks defined via `Do`, not to the other setup callbacks like `Returns` or `Throws`.
886+
860887
#### Invocation counter
861888

862889
Access the zero-based invocation counter in callbacks:

0 commit comments

Comments
 (0)