Skip to content

Commit afe41d2

Browse files
committed
Add callback support to BbQ.MockLite framework
Introduced a robust callback mechanism for executing custom logic during mock interactions. Added support for method callbacks (`OnCall`) with or without argument matchers, and property access callbacks (`OnPropertyAccess`, `OnGetCallback`, `OnSetCallback`) for tracking property reads and writes. Enhanced the `README.md` with detailed examples and documentation on callback usage. Updated the core runtime (`RuntimeProxy`) to include callback registration and execution. Extended the `Mock<T>` class with new callback methods and refactored helper functions. Added comprehensive unit tests in `MockCallbackTests` to cover various callback scenarios, including conditional callbacks, property access tracking, and integration workflows. Updated project structure and documentation links to reflect the new features. Improved code comments and adjusted invocation recording to ensure compatibility with callbacks.
1 parent dc84bde commit afe41d2

File tree

4 files changed

+999
-11
lines changed

4 files changed

+999
-11
lines changed

README.md

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ A lightweight, high-performance mocking framework for .NET that combines compile
1111
- 📝 **Invocation Recording** - Automatically records all method invocations with timestamps for verification
1212
- 🎯 **Argument Matching** - Pattern matching for mock setup and verification
1313
- 🔍 **Verification** - Flexible verification with Times predicates (`Once`, `Never`, `Exactly`, `AtLeast`, `AtMost`)
14+
- 🔗 **Callbacks** - Execute custom logic when methods are called or properties are accessed
1415
- 🎓 **Easy API** - Simple, intuitive API inspired by popular mocking frameworks
1516

1617
## Getting Started
@@ -108,10 +109,72 @@ foreach (var invocation in builder.Invocations)
108109
- `VerifySet<TProp>(property, times)` - Verify property setter call count
109110
- `VerifySet<TProp>(property, matcher, times)` - Verify property setter with value matching
110111

112+
**Callback Methods:**
113+
- `OnCall(expression, callback)` - Execute logic when method is called
114+
- `OnCall(expression, matcher, callback)` - Execute logic when method is called with matching arguments
115+
- `OnPropertyAccess<T>(property, callback)` - Execute logic on property get or set
116+
- `OnGetCallback<T>(property, callback)` - Execute logic when property getter is accessed
117+
- `OnSetCallback<T>(property, callback)` - Execute logic when property setter is called
118+
- `OnSetCallback<T>(property, matcher, callback)` - Execute logic when property setter is called with matching value
119+
111120
**Properties:**
112121
- `Object` - Get the mock instance
113122
- `Invocations` - Access all recorded invocations for custom verification
114123

124+
## Callbacks for Custom Logic Execution
125+
126+
BbQ.MockLite supports callbacks that execute custom logic when methods are called or properties are accessed. This is useful for audit logging, state management, and complex verification scenarios.
127+
128+
```csharp
129+
using BbQ.MockLite;
130+
131+
// Track method calls with custom logic
132+
var auditLog = new List<string>();
133+
var builder = Mock.Create<IUserRepository>()
134+
.OnCall(x => x.GetUser(It.IsAny<string>()),
135+
args => auditLog.Add($"GetUser called with: {args[0]}"))
136+
.OnCall(x => x.SaveUser(It.IsAny<User>()),
137+
args => args[0] is User u && u.IsAdmin,
138+
args => auditLog.Add($"Admin user saved: {((User)args[0]).Name}"));
139+
140+
var mock = builder.Object;
141+
142+
// Use the mock
143+
var user = mock.GetUser("123");
144+
mock.SaveUser(new User { Name = "Admin", IsAdmin = true });
145+
146+
// Verify callbacks were executed
147+
Assert.Equal(2, auditLog.Count);
148+
```
149+
150+
### Callback Patterns
151+
152+
**Track method calls:**
153+
```csharp
154+
var callCount = 0;
155+
mock.OnCall(x => x.Process(It.IsAny<string>()),
156+
args => callCount++);
157+
```
158+
159+
**Conditional callbacks:**
160+
```csharp
161+
var adminActions = new List<string>();
162+
mock.OnCall(
163+
x => x.Execute(It.IsAny<string>()),
164+
args => args[0] is string s && s.StartsWith("admin"),
165+
args => adminActions.Add((string)args[0]));
166+
```
167+
168+
**Track property access:**
169+
```csharp
170+
var propertyLog = new List<string>();
171+
mock
172+
.OnGetCallback(x => x.Status,
173+
() => propertyLog.Add("Status read"))
174+
.OnSetCallback(x => x.Status,
175+
value => propertyLog.Add($"Status set to: {value}"));
176+
```
177+
115178
## Two-Tier Mocking Strategy
116179

117180
BbQ.MockLite uses an intelligent two-tier approach:
@@ -208,7 +271,7 @@ var mock = Mock.Of<IAsyncRepository>();
208271

209272
## Project Structure
210273

211-
- **BbQ.MockLite** - Core runtime helpers (DispatchProxy, invocation recording)
274+
- **BbQ.MockLite** - Core runtime helpers (DispatchProxy, invocation recording, callbacks)
212275
- **BbQ.MockLite.Generators** - Source generator for compile-time mock generation
213276
- **BbQ.MockLite.Sample** - Comprehensive examples and usage patterns
214277
- **BbQ.MockLite.Tests** - Unit tests for core functionality
@@ -222,9 +285,9 @@ BbQ.MockLite Framework
222285
│ └── Generates optimized MockXxx classes from [GenerateMock] interfaces
223286
224287
├── Core Runtime (Execution-time)
225-
│ ├── RuntimeProxy<T> - DispatchProxy-based fallback implementation
288+
│ ├── RuntimeProxy<T> - DispatchProxy-based fallback with callback support
226289
│ ├── Invocation - Records method calls with timestamps
227-
│ ├── MockBuilder<T> - Fluent API for advanced mock creation
290+
│ ├── Mock<T> - Fluent builder for setup, verification, and callbacks
228291
│ └── Mock - Factory for creating mock instances
229292
230293
└── Supporting Infrastructure
@@ -239,7 +302,8 @@ BbQ.MockLite Framework
239302
2. **Setup First** - Configure mock behavior before using in tests
240303
3. **Verify Behaviors** - Use the verification API to assert interactions
241304
4. **Use Argument Matchers** - `It.IsAny<T>()` for flexible matching
242-
5. **Record Invocations** - Leverage invocation recording for complex verification scenarios
305+
5. **Leverage Callbacks** - Use callbacks for audit logging and state tracking
306+
6. **Record Invocations** - Leverage invocation recording for complex verification scenarios
243307

244308
## Examples
245309

@@ -251,8 +315,16 @@ See the [BbQ.MockLite.Sample](./src/MockLite.Sample/Program.cs) project for comp
251315
- Exception handling
252316
- Async methods
253317
- Invocation recording
318+
- Callback usage
254319
- Complete integration scenarios
255320

321+
## Documentation
322+
323+
For detailed documentation on callbacks and advanced features, see:
324+
- [Callback Feature Guide](./CALLBACK_FEATURE_GUIDE.md) - Complete API reference
325+
- [Callback Quick Reference](./CALLBACK_QUICK_REFERENCE.md) - Quick start and examples
326+
- [Feature Summary](./FEATURE_COMPLETE_SUMMARY.md) - Implementation overview
327+
256328
## Requirements
257329

258330
- .NET 8.0 or later

0 commit comments

Comments
 (0)