Base Implementation¶
Forward calls from imposters to the original class implementation instead of configuring custom behavior.
Note
Base Implementation is available for overrideable and non-abstract class members only.
Methods¶
Target type used in examples:
Example
using Imposter.Abstractions;
[assembly: GenerateImposter(typeof(MyService))]
public class MyService
{
public virtual int Add(int a, int b)
=> a + b;
public virtual System.Threading.Tasks.Task ProcessAsync(string s)
=> System.Threading.Tasks.Task.CompletedTask;
public virtual int MightFail(int v)
=> throw new System.InvalidOperationException("fail");
}
Basic example¶
Example
var imposter = new MyServiceImposter();
var service = imposter.Instance();
// Forward calls to the original implementation
imposter.Add(Arg<int>.Any(), Arg<int>.Any()).UseBaseImplementation();
service.Add(2, 5); // 7 (calls MyService.Add)
With matchers and sequencing¶
Example
var imposter = new MyServiceImposter();
var service = imposter.Instance();
// Otherwise return a specific value (fallback)
imposter.Add(Arg<int>.Any(), Arg<int>.Any()).Returns(-1);
// Only forward when the first value is positive (more specific rule)
imposter.Add(Arg<int>.Is(x => x > 0), Arg<int>.Any()).UseBaseImplementation();
service.Add(2, 3); // 5 (base)
service.Add(-2, 3); // -1 (fallback)
Sequence with Then() if you need to call base once and then switch behavior:
Example
var imposter = new MyServiceImposter();
var service = imposter.Instance();
imposter.Add(Arg<int>.Any(), Arg<int>.Any())
.UseBaseImplementation()
.Then()
.Returns(100);
service.Add(1, 1); // base -> 2
service.Add(1, 1); // 100
Async and exceptions¶
Example
var imposter = new MyServiceImposter();
var service = imposter.Instance();
// Async forwarding
imposter.ProcessAsync(Arg<string>.Any()).UseBaseImplementation();
await service.ProcessAsync("x"); // runs class implementation
// Exceptions from base flow to the caller
imposter.MightFail(Arg<int>.Any()).UseBaseImplementation();
Should.Throw<InvalidOperationException>(() => service.MightFail(5));
Properties¶
For class targets with virtual properties, you can forward getters and setters to the base implementation.
Example
var imposter = new ClassWithVirtualPropertyImposter();
imposter.VirtualProperty.Getter().UseBaseImplementation();
var service = imposter.Instance();
var value = service.VirtualProperty; // uses base implementation
Example
var imposter = new ClassWithVirtualPropertyImposter();
imposter.VirtualProperty.Setter(Arg<string>.Any()).UseBaseImplementation();
var service = imposter.Instance();
service.VirtualProperty = "value"; // uses base implementation
This is useful when you want imposters to preserve class invariants or initialization logic defined in virtual properties.
Indexers¶
Class targets with virtual indexers also support UseBaseImplementation() on getter and setter builders.
Example
var imposter = new IIndexerSetupSutImposter();
imposter[Arg<int>.Any(), Arg<string>.Any(), Arg<object>.Any()].Getter().UseBaseImplementation();
var service = imposter.Instance();
var result = service[1, "key", new object()]; // uses base implementation
Example
var imposter = new IIndexerSetupSutImposter();
imposter[Arg<int>.Any(), Arg<string>.Any(), Arg<object>.Any()].Setter().UseBaseImplementation();
var service = imposter.Instance();
service[1, "key", new object()] = 42; // uses base implementation
Use this when a virtual indexer encapsulates non-trivial logic (e.g., backing collections or validation) and you want imposters to reuse it rather than reimplement it in tests.