diff --git a/Docs/pages/setup/01-properties.md b/Docs/pages/setup/01-properties.md index e287a0d7..9b0bc47f 100644 --- a/Docs/pages/setup/01-properties.md +++ b/Docs/pages/setup/01-properties.md @@ -13,7 +13,7 @@ sut.SetupMock.Property.TotalDispensed.InitializeWith(42); **Returns / Throws** -Alternatively, set up properties with `Returns` and `Throws` (supports sequences): +Set up properties with `Returns` and `Throws` (supports sequences): ```csharp sut.SetupMock.Property.TotalDispensed @@ -23,6 +23,13 @@ sut.SetupMock.Property.TotalDispensed .Returns(4); ``` +You can also return a value based on the previous value: + +```csharp +sut.SetupMock.Property.TotalDispensed + .Returns((current) => current + 10); // Increment by 10 each read +``` + **Callbacks** Register callbacks on the setter or getter: @@ -31,3 +38,29 @@ Register callbacks on the setter or getter: sut.SetupMock.Property.TotalDispensed.OnGet.Do(() => Console.WriteLine("TotalDispensed was read!")); sut.SetupMock.Property.TotalDispensed.OnSet.Do((oldValue, newValue) => Console.WriteLine($"Changed from {oldValue} to {newValue}!") ); ``` + +Callbacks can also receive the invocation counter and current value: + +```csharp +// Getter with counter and current value +sut.SetupMock.Property.TotalDispensed + .OnGet.Do((int count, int value) => + Console.WriteLine($"Read #{count}, current value: {value}")); + +// Setter with counter and new value +sut.SetupMock.Property.TotalDispensed + .OnSet.Do((int count, int newValue) => + Console.WriteLine($"Set #{count} to {newValue}")); +``` + +**Register** + +Register a setup without providing a value (useful with `ThrowWhenNotSetup`): + +```csharp +var strictMock = Mock.Create( + new MockBehavior { ThrowWhenNotSetup = true }); + +// Register property without value - won't throw +strictMock.SetupMock.Property.TotalDispensed.Register(); +``` diff --git a/Docs/pages/setup/03-indexers.md b/Docs/pages/setup/03-indexers.md index 8fe95e5a..6ccad3a9 100644 --- a/Docs/pages/setup/03-indexers.md +++ b/Docs/pages/setup/03-indexers.md @@ -14,8 +14,24 @@ sut.SetupMock.Indexer(It.Is("Dark")) - `.InitializeWith(…)` can take a value or a callback with parameters. - `.Returns(…)` and `.Throws(…)` support direct values, callbacks, and callbacks with parameters and/or the current - value. -- `.OnGet.Do(…)` and `.OnSet.Do(…)` support callbacks with or without parameters. + value. You can also return a value based on the previous value: + ```csharp + sut.SetupMock.Indexer(It.Is("Dark")) + .Returns((string type, int current) => current + 10); // Increment by 10 each read + ``` +- `.OnGet.Do(…)` and `.OnSet.Do(…)` support callbacks with or without parameters. Callbacks can receive the invocation + counter, indexer parameters, and current value: + ```csharp + // Getter with counter, parameter, and current value + sut.SetupMock.Indexer(It.IsAny()) + .OnGet.Do((int count, string type, int value) => + Console.WriteLine($"Read #{count} for {type}, current value: {value}")); + + // Setter with counter, parameter, and new value + sut.SetupMock.Indexer(It.IsAny()) + .OnSet.Do((int count, string type, int newValue) => + Console.WriteLine($"Set #{count} for {type} to {newValue}")); + ``` - `.Returns(…)` and `.Throws(…)` can be chained to define a sequence of behaviors, which are cycled through on each call. - Use `.SkippingBaseClass(…)` to override the base class behavior for a specific indexer (only for class mocks). diff --git a/README.md b/README.md index 38611181..6bd56bca 100644 --- a/README.md +++ b/README.md @@ -193,7 +193,7 @@ sut.SetupMock.Property.TotalDispensed.InitializeWith(42); **Returns / Throws** -Alternatively, set up properties with `Returns` and `Throws` (supports sequences): +Set up properties with `Returns` and `Throws` (supports sequences): ```csharp sut.SetupMock.Property.TotalDispensed @@ -203,6 +203,13 @@ sut.SetupMock.Property.TotalDispensed .Returns(4); ``` +You can also return a value based on the previous value: + +```csharp +sut.SetupMock.Property.TotalDispensed + .Returns((current) => current + 10); // Increment by 10 each read +``` + **Callbacks** Register callbacks on the setter or getter: @@ -212,6 +219,32 @@ sut.SetupMock.Property.TotalDispensed.OnGet.Do(() => Console.WriteLine("TotalDis sut.SetupMock.Property.TotalDispensed.OnSet.Do((oldValue, newValue) => Console.WriteLine($"Changed from {oldValue} to {newValue}!") ); ``` +Callbacks can also receive the invocation counter and current value: + +```csharp +// Getter with counter and current value +sut.SetupMock.Property.TotalDispensed + .OnGet.Do((int count, int value) => + Console.WriteLine($"Read #{count}, current value: {value}")); + +// Setter with counter and new value +sut.SetupMock.Property.TotalDispensed + .OnSet.Do((int count, int newValue) => + Console.WriteLine($"Set #{count} to {newValue}")); +``` + +**Register** + +Register a setup without providing a value (useful with `ThrowWhenNotSetup`): + +```csharp +var strictMock = Mock.Create( + new MockBehavior { ThrowWhenNotSetup = true }); + +// Register property without value - won't throw +strictMock.SetupMock.Property.TotalDispensed.Register(); +``` + ### Methods Use `mock.SetupMock.Method.MethodName(…)` to set up methods. You can specify argument matchers for each parameter. @@ -275,8 +308,24 @@ sut.SetupMock.Indexer(It.Is("Dark")) - `.InitializeWith(…)` can take a value or a callback with parameters. - `.Returns(…)` and `.Throws(…)` support direct values, callbacks, and callbacks with parameters and/or the current - value. -- `.OnGet.Do(…)` and `.OnSet.Do(…)` support callbacks with or without parameters. + value. You can also return a value based on the previous value: + ```csharp + sut.SetupMock.Indexer(It.Is("Dark")) + .Returns((string type, int current) => current + 10); // Increment by 10 each read + ``` +- `.OnGet.Do(…)` and `.OnSet.Do(…)` support callbacks with or without parameters. Callbacks can receive the invocation + counter, indexer parameters, and current value: + ```csharp + // Getter with counter, parameter, and current value + sut.SetupMock.Indexer(It.IsAny()) + .OnGet.Do((int count, string type, int value) => + Console.WriteLine($"Read #{count} for {type}, current value: {value}")); + + // Setter with counter, parameter, and new value + sut.SetupMock.Indexer(It.IsAny()) + .OnSet.Do((int count, string type, int newValue) => + Console.WriteLine($"Set #{count} for {type} to {newValue}")); + ``` - `.Returns(…)` and `.Throws(…)` can be chained to define a sequence of behaviors, which are cycled through on each call. - Use `.SkippingBaseClass(…)` to override the base class behavior for a specific indexer (only for class mocks).