override<T, S extends Step<T>> method

void override<T, S extends Step<T>>(
  1. S step,
  2. FutureOr<T> value
)

Override step with value, ensuring that step evaluates to value when run is called in this Runner.

Overriding a Step is a useful technique for injecting input that steps depend on, as illstrated in the example below. It can also be useful for injecting mock objects or fakes when writing tests.

Overriding a step after it has been evaluated or overriden once is not allowed.

Example overriding a step to provide input

/// A step that provides a message, this is a _virtual step_ because it
/// doesn't have an implementation instead it throws an error. Hence, to
/// evaluate a step that depends on [messageStep] it is necessary to
/// override this step, by injecting a value to replace it.
final Step<String> messageStep = Step.define('message').build(
  () => throw UnimplementedError('message must be overriden with input'),
);

/// A step that provides date and time
final dateTimeStep =
    Step.define('date-time').build(() => DateTime.now().toString());

/// A step which has side effects.
final Step<void> printStep = Step.define('print')
    // Dependencies:
    .dep(messageStep)
    .dep(dateTimeStep)
    .build((
  msg, // result from evaluation of messageStep
  time, // result from evaluation of dateTimeStep
) {
  print('$msg at $time');
});

Future<void> main() async {
  final r = Runner();
  // Override [messageStep] to provide an input value.
  r.override(messageStep, 'hello world');
  // Evaluate [printStep] which in turn evaluates [dateTimeStep], and re-uses
  // the overridden value for [messageStep].
  await r.run(printStep);
}

Implementation

void override<T, S extends Step<T>>(S step, FutureOr<T> value) {
  if (_cache.containsKey(step)) {
    throw StateError('Value for $step is already cached');
  }
  _cache[step] = Future.value(value);
}