diff --git a/Docs/pages/advanced-features/01-working-with-protected-members.md b/Docs/pages/advanced-features/01-working-with-protected-members.md new file mode 100644 index 00000000..10017d34 --- /dev/null +++ b/Docs/pages/advanced-features/01-working-with-protected-members.md @@ -0,0 +1,59 @@ +# Working with protected members + +Mockolate allows you to set up and verify protected virtual members on class mocks. Access protected members using the +`.Protected` property: + +## Example: + +```csharp +public abstract class ChocolateDispenser +{ + protected virtual bool DispenseInternal(string type, int amount) => true; + protected virtual int InternalStock { get; set; } +} + +var sut = Mock.Create(); +``` + +### Setup + +```csharp +// Setup protected method +sut.SetupMock.Protected.Method.DispenseInternal( + It.Is("Dark"), It.IsAny()) + .Returns(true); + +// Setup protected property +sut.SetupMock.Protected.Property.InternalStock.InitializeWith(100); +``` + +**Notes:** + +- Protected members can be set up and verified just like public members, using the `.Protected` accessor. +- All setup options (`.Returns()`, `.Throws()`, `.Do()`, `.InitializeWith()`, etc.) work with protected members. + +### Verification + +```csharp +// Verify protected method was invoked +sut.VerifyMock.Invoked.Protected.DispenseInternal( + It.Is("Dark"), It.IsAny()).Once(); + +// Verify protected property was read +sut.VerifyMock.Got.Protected.InternalStock().AtLeastOnce(); + +// Verify protected property was set +sut.VerifyMock.Set.Protected.InternalStock(It.Is(100)).Once(); + +// Verify protected indexer was read +sut.VerifyMock.GotProtectedIndexer(It.Is(0)).Once(); + +// Verify protected indexer was set +sut.VerifyMock.SetProtectedIndexer(It.Is(0), It.Is(42)).Once(); +``` + +**Note:** + +- All verification options (argument matchers, count assertions) work the same for protected members as for public + members. +- Protected indexers are supported using `.GotProtectedIndexer()`/`.SetProtectedIndexer()` for verification. diff --git a/Docs/pages/advanced-features/01-advanced-callback-features.md b/Docs/pages/advanced-features/02-advanced-callback-features.md similarity index 100% rename from Docs/pages/advanced-features/01-advanced-callback-features.md rename to Docs/pages/advanced-features/02-advanced-callback-features.md diff --git a/Mockolate.slnx b/Mockolate.slnx index abd6ea6e..4edf488b 100644 --- a/Mockolate.slnx +++ b/Mockolate.slnx @@ -49,6 +49,8 @@ + + diff --git a/README.md b/README.md index a72960c2..0313a92b 100644 --- a/README.md +++ b/README.md @@ -619,6 +619,66 @@ If the order is incorrect or a call is missing, a `MockVerificationException` wi ## Advanced Features +### Working with protected members + +Mockolate allows you to set up and verify protected virtual members on class mocks. Access protected members using the +`.Protected` property: + +#### Example: + +```csharp +public abstract class ChocolateDispenser +{ + protected virtual bool DispenseInternal(string type, int amount) => true; + protected virtual int InternalStock { get; set; } +} + +var sut = Mock.Create(); +``` + +##### Setup + +```csharp +// Setup protected method +sut.SetupMock.Protected.Method.DispenseInternal( + It.Is("Dark"), It.IsAny()) + .Returns(true); + +// Setup protected property +sut.SetupMock.Protected.Property.InternalStock.InitializeWith(100); +``` + +**Notes:** + +- Protected members can be set up and verified just like public members, using the `.Protected` accessor. +- All setup options (`.Returns()`, `.Throws()`, `.Do()`, `.InitializeWith()`, etc.) work with protected members. + +##### Verification + +```csharp +// Verify protected method was invoked +sut.VerifyMock.Invoked.Protected.DispenseInternal( + It.Is("Dark"), It.IsAny()).Once(); + +// Verify protected property was read +sut.VerifyMock.Got.Protected.InternalStock().AtLeastOnce(); + +// Verify protected property was set +sut.VerifyMock.Set.Protected.InternalStock(It.Is(100)).Once(); + +// Verify protected indexer was read +sut.VerifyMock.GotProtectedIndexer(It.Is(0)).Once(); + +// Verify protected indexer was set +sut.VerifyMock.SetProtectedIndexer(It.Is(0), It.Is(42)).Once(); +``` + +**Note:** + +- All verification options (argument matchers, count assertions) work the same for protected members as for public + members. +- Protected indexers are supported using `.GotProtectedIndexer()`/`.SetProtectedIndexer()` for verification. + ### Advanced callback features #### Conditional callbacks