-
-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
2 / 22 of 2 issues completedDescription
Description
Support the ability to wrap a concrete instance in Mockolate, similar to the behavior described in FakeItEasy's "calling wrapped methods" documentation.
Developers should be able to use Mockolate not only for interfaces or abstract classes but also to wrap existing concrete objects. This allows for interception, verification, and stubbing of behavior in already-created instances.
Expected Behavior
- Allow an existing concrete object to be passed to Mockolate for wrapping
- Mockolate should intercept and verify calls to methods on the wrapped instance
- Non-overridden methods should delegate to the original underlying object
- Test doubles can be created that wrap and extend the behavior of a concrete instance
- Clearly document the API for creating a wrapped instance and the limitations or caveats involved
Implementation Plan: Support Wrapping a Concrete Instance (Mockolate)
1. API Surface Proposal
public static class Mock
{
/// <summary>
/// Wraps a concrete instance with a mock proxy that intercepts and delegates method calls,
/// supporting setup and verification on the wrapped instance.
/// </summary>
public static T Wrap<T>(T instance) where T : class;
}- Usage Example:
var myInstance = new MyService(); var wrapped = Mock.Wrap(myInstance); // Setup example: Override method behavior via SetupMock wrapped.SetupMock.Method.DoSomething() .Returns(() => "Mocked Value"); // Use original implementation unless overridden var result = wrapped.OtherMethod(); // delegates to myInstance.OtherMethod() // Verification example: Check interactions wrapped.VerifyMock.Invoked.DoSomething().Exactly(1);
2. Proxy Generation
- Use proxy or source generator techniques to create a wrapper that intercepts calls:
- For wrapped methods, use the override from
SetupMock, otherwise delegate to the original instance. - Use event and property interception if supported/required.
- For wrapped methods, use the override from
3. Setup and Verification Syntax
-
Setup:
- Use
.SetupMockfluent APIs to override specific behavior (e.g. methods, properties, indexers). - Supports argument matchers, call count limits, and custom return delegates.
- Use
-
Verification:
- Use
.VerifyMockfor call assertions and invocation matching. - Standard pattern for asserting invocations and argument matching.
- Use
4. Delegation Rules
- Unless overridden with
.SetupMock, calls and property accesses are delegated to the original object. - Document any limitations—e.g., sealed/non-virtual methods, static members.
5. Testing
- Ensure comprehensive tests for:
- Wrapping and interacting with various types (interfaces, concrete classes, inherited types).
- Overriding via
.SetupMock, verifying via.VerifyMock. - Edge cases coverage.
6. Documentation
- Provide examples using the above API, matching the README style.
- Clarify caveats of concrete instance wrapping.
Example Usage in Mockolate Syntax
var service = new MyService();
var wrapped = Mock.Wrap(service);
// Setup override
wrapped.SetupMock.Method.GetData().Returns(() => "MockedData");
// Unmocked methods delegate to service
wrapped.SetupMock.Method.Add(2, 3).KeepOriginalBehavior();
var result = wrapped.Add(2, 3); // Calls original instance
var data = wrapped.GetData(); // Returns "MockedData"
// Verify method invocations
wrapped.VerifyMock.Invoked.GetData().Exactly(1);Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels