Skip to content

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.