use<T extends Object> static method

Future<T> use<T extends Object>(
  1. Module module,
  2. FutureOr<T> body(
    1. TestRuntime testRuntime
    ), {
  3. ResolverBackend? backend,
  4. CleanupFailureObserver? cleanupFailureObserver,
  5. Iterable<RuntimeObserver> observers = const <RuntimeObserver>[],
  6. RuntimeObserverErrorHandler? observerErrorHandler,
})

Start a harness, execute body, and close it even when body throws.

Implementation

static Future<T> use<T extends Object>(
  Module module,
  FutureOr<T> Function(TestRuntime testRuntime) body, {
  ResolverBackend? backend,
  CleanupFailureObserver? cleanupFailureObserver,
  Iterable<RuntimeObserver> observers = const <RuntimeObserver>[],
  RuntimeObserverErrorHandler? observerErrorHandler,
}) async {
  final harness = await start(
    module,
    backend: backend,
    cleanupFailureObserver: cleanupFailureObserver,
    observers: observers,
    observerErrorHandler: observerErrorHandler,
  );

  Object? primaryError;
  StackTrace? primaryStackTrace;
  T? value;

  try {
    value = await Future<T>.sync(() => body(harness));
  } catch (error, stackTrace) {
    primaryError = error;
    primaryStackTrace = stackTrace;
  }

  try {
    await harness.close();
  } catch (closeError, closeStackTrace) {
    if (primaryError == null) {
      Error.throwWithStackTrace(closeError, closeStackTrace);
    }

    Error.throwWithStackTrace(
      CompositeDefect(
        primary: primaryError,
        primaryStackTrace: primaryStackTrace!,
        secondary: closeError,
        secondaryStackTrace: closeStackTrace,
      ),
      primaryStackTrace,
    );
  }

  if (primaryError != null) {
    Error.throwWithStackTrace(primaryError, primaryStackTrace!);
  }

  return value as T;
}