Skip to content

API reference

The exported surface of vitest-auto-spy and its subpaths.

ExportDescription
createSpyFromClass(Class, methodsOrConfig?)Build a fully-typed Spy<T> from a class
createAutoMock<T>(overrides?)Build a Spy<T> from a type/interface alone (Proxy, no class)
createMock<T>(partial?)Build a plain, spy-free T from the fields a test seeds — for data shapes, not collaborators
mockDeep<T>(overrides?, options?)Recursive DeepMockProxy<T> — nested access auto-creates chainable spies; { selfReturning: true } chains through calls too
clearAutoSpy(spy) / resetAutoSpy(spy)Clear calls (keep config) / full reset of every spy inside an assembled spy
provideAutoSpy(Class, methodsOrConfig?)Angular { provide, useValue } shorthand (/angular), abstract classes included; NestJS / Vue variants in their subpaths
injectSpy(token)TestBed.inject typed as Spy<T> (/angular); NestJS variant takes (moduleRef, token)
createFunctionSpy(name)A single standalone function spy with all helpers
createObservableWithValues(configs, opts?)Build an Observable from value configs (/rxjs)
mockReadonlyProp / mockReadonlyPropGetter / mockValueProp / mockAccessorsPropMock readonly / writable / accessor / signal props (core, also re-exported from /angular)
restoreMockedProps() / countMockedProps()Undo every mock*Prop patch / how many are still applied
expectEmission(source$, opts?) / expectEmissions(source$, n, opts?) / expectNoEmission(source$, opts?)Assert an Observable without a subscribe callback that may never run; the emitted type is inferred
expectCompletion(source$, opts?)Assert that a stream terminates — the Observable<void> case firstValueFrom rejects with EmptyError
setEmissionTimeout(ms)Change the process-wide default wait of the emission helpers; for a suite under global fake timers
asInstance(spy) / asSpy(instance)The two named views between Spy<T> and T, instead of as any
createSpyClass(Class, config?)A spy that can be called with new; records calls and instances
setupAutoSpy(opts?)Property restore, duplicate-copy detection, stray timers and rejections, mock-registry hygiene — one call (/setup)
setupFakeTimers(config?, opts?) / advanceTimers(ms?)Paired fake-timer install/restore, and an advance that settles queued microtasks (/setup)
stubIntersectionObserver() / stubResizeObserver() / stubMutationObserver() / stubObserver(name)Replace an observer global with one the spec drives; restored by restoreMockedProps()
intersectionEntry(target, isIntersecting, overrides?)Build one IntersectionObserverEntry without the fields nothing reads
mockResourceProp(object, prop, initial)Replace a resource-valued property with a double the spec drives — set / fail / loading / spied reload (/angular)
mockSignalProp(object, prop, initial)Replace a signal-valued property with a real writable signal, and hand back the handle (/angular)
blockNetwork(options?)Close fetch, XHR and sendBeacon, naming what was requested (/setup)
trackStrayRejections() / countStrayRejections() / flushStrayRejections()Read back the promise rejections zone.js swallowed into console.error (/setup)
trackMockRegistry() / keepMockRegistered(mock) / pruneMockRegistry()Keep @vitest/spy's ever-growing mock registry to the mocks that outlive a file (/setup)
guardGlobalPatches(reaction)Name the test that redefined a global property as non-configurable (/setup)
installPerTest(install)Re-install a stub before every test of the block, and read back the current handle (/setup)
stubMediaElement(opts?)A <video> / <audio> that plays, reports a duration and fires the media events
assertMocked(namespace, opts?)Fail when the vi.mock() this spec relies on silently did not apply
moduleNamespace(exports, opts?)The vi.mock factory result an interop probe recognises (default + __esModule)
flushEventLoopUntil(isDone, opts?)Real event-loop turns until a condition holds, with a budget instead of a hang
diffByField(actual, expected)Which field of an array of records moved, in how many elements — the diff the reporter collapses
setupAngularTestEnv(opts?)Zone and zoneless spec files in one worker, switching platforms per file (/angular)
provideAutoSpyForToken(token, overrides?){ provide, useValue } for an InjectionToken, with the spy built from the token's type (/angular)
createDirectiveHost(opts)A standalone host for a directive under test, with its scope where the compiler reads it (/angular)
registerDirectiveMatchers()Adds expect(fixture).toHaveDirectiveApplied(Directive, selector?) (/angular)
asInstances(...spies)asInstance for a whole argument list, in one edit against one compiler error
captureArg<T>()Take hold of an argument the code under test built, rather than describing it — for assertions, not calledWith
narrow(value, predicate) / narrow.byKey / narrow.observableThe branch of a union a test knows it got, failing with the shape the value actually had
withOverrides(model, overrides?)A fixture from a model instance: its getters read once, as data
compareTestRuns(a, b, root?) / formatTestRunComparison(diff) / summarizeTestRun(report, root?)Whether a migration lost a test — the set of names, which counters cannot answer
installProxyZonePatch(opts?)fakeAsync / waitForAsync on Vitest (/zone, which installs it on import)
restoreTimerGlobals() / getWatchedTimerGlobals()Put back timer globals the fakes deleted / the names captured (/setup)
renderShallow(Component, opts?)TestBed component without its children and (by default) its template (/angular)
createWithAutoSpies(Class, opts?)Build a class through Angular DI with every unprovided token auto-spied (/angular)
stable(fixture, opts?) / flushEffects()Zoneless waiting: flush effects, then await the fixture, with a 2 s budget that names the cause (/angular)
settleResource(resource, opts?)Tick until an httpResource() / resource() / rxResource() leaves loading (/angular)
registerResourceMatchers()Adds toBeLoading / toHaveResourceValue / toHaveResourceError; the value matcher fails an unresolved resource (/angular)
registerSignalMatchers()Adds expect(sig).toHaveSignalValue(value) (/angular)
enableTestBedDiagnostics(opts?)Per-file report of how much of a spec's time went into TestBed (/angular)
registerDomGlobals(opts?)Install a DOM into a runtime that ships none; returns the registrar used (/bun-angular)
createJsdomRegistrar(opts) / createGlobalRegistratorRegistrar(opts)The two DOM strategies registerDomGlobals tries, for a custom preload (/bun-angular)
copyWindowGlobals(source, target)Copy a window's properties onto a global-like target, without clobbering runtime built-ins
inlineAngularResources(source, path, opts?)Rewrite templateUrl / styleUrl / styleUrls into inline template / styles
consoleDebugSpyconsoleWarnSpySilent typed spies replacing the global console methods on import (/console)
installConsoleSpies() / resetConsoleSpies() / restoreConsole()Install / clear / undo the console spies (/console)
errorHandlerThe mustBeCalledWith argument-mismatch error helper
vitest-auto-spy/eslint-pluginNine flat-config lint rules that steer a suite onto these helpers

Helper surface by return type

Spied sync method: mockReturnValue, calledWith(...), mustBeCalledWith(...)calledWith / mustBeCalledWith accept asymmetric matchers (expect.any, expect.objectContaining, …)

Spied Promise method: resolveWith, rejectWith, resolveWithPerCall; outcomes are recorded on mock.settledResults (native on Vitest, polyfilled on Bun / node:test)

Spied Observable method / property: nextWith, nextOneTimeWith, nextWithValues, nextWithPerCall, throwWith, complete, returnSubject

Configuration

ClassSpyConfiguration: methodsToSpyOn (added to the discovered methods), onlyMethodsToSpyOn (spy on nothing but these — discovery skipped), instanceMethodsToSpyOn (same behaviour as methodsToSpyOn, named for callables that live on the instance — signal() fields, arrow props, signalStore() methods), observablePropsToSpyOn, gettersToSpyOn, settersToSpyOn (any string key — "is an accessor" is a fact about the descriptor, not about the value's type, so a signal-valued getter is nameable), returns (return values installed as the spy is built), autoSpyAccessors (auto-discover getters/setters), fillMissing (answer a name the prototype never carried with a spy — for a partially abstract class, where the erased members leave the empty-prototype fallback unable to fire), lazySpies (build each method spy on first access — the provideAutoSpy default on Angular)

ValueConfig (for nextWithValues): { value, delay? } | { errorValue, delay? } | { complete?, delay? }.

Public types

Spy<T> — the assembled spy. A mapped type over T: every method becomes AddSpyMethodsByReturnTypes<Method> (the mock plus the helpers its return type earns), every Observable property gains the observable helpers, everything else keeps its own type. It also adds an accessorSpies bag: accessorSpies.getters[key] / accessorSpies.setters[key].

Because it is a mapped type it drops #private and private members, so Spy<T> is not assignable to T. Declare the variable as Spy<T>injectSpy(X) already returns it — or bridge the two with asInstance / asSpy.

ClassType<T> — a constructor of T, the token createSpyFromClass / provideAutoSpy take. The construct signature is abstract, so an abstract class DI token is accepted; nothing here ever calls new on it.

DeepMockProxy<T> — what mockDeep<T>() returns: object properties become nested deep mocks, so mock.a.b.c is chainable without seeding. Depth comes from property access: a chain that goes through a call (a.b().c()) needs { selfReturning: true }.

SubscribableLike<T> / CallbackSubscribable<T> / EmissionSource<T> — the two subscription contracts the emission helpers accept (an observer object, as rxjs takes; a bare next callback, as Angular's output() takes) and their union.

AddSpyMethodsByReturnTypes<Method> — the per-method surface: the mock itself intersected with calledWith / mustBeCalledWith, plus the Promise or Observable helper bundle when the return type earns one.

Spy<T, Options> — the second parameter is { overload?: 'first' | 'last' }. Parameters and ReturnType read the last signature of an overloaded method, which on a generated API client is observe: 'events' — the one nobody calls. Overload<F, 0> names one signature on its own.

DeepPartial<T> — what createMock / createAutoMock take: partial at every depth, and a key T does not have is still rejected at every depth. Built-ins (Date, Map, Promise, functions) pass through untouched. A real value is accepted wherever a partial is, so a host object such as a NodeList stays assignable to the mapping of itself.

ClassSpyConfiguration<T>, ValueConfig<T>, NextValueConfig, ErrorValueConfig, CompleteValueConfig, ValueConfigPerCall, OnlyMethodKeysOf<T>, OnlyObservablePropsOf<T>, AccessorKeysOf<T>, MethodReturns<T>, PropStubValue<V>, SpyOptions, Overloads<F> are exported from the core as well.

Exports by subpath

Every runtime and framework subpath re-exports the whole core on top of what it adds, so a spec never needs two imports from this package.

SubpathAdds on top of the core
vitest-auto-spy— (this is the core; registers the Vitest adapter)
/bun— (registers the bun:test adapter)
/node— (registers the node:test adapter)
/bun-angularprovideAutoSpy, injectSpy, renderShallow, createWithAutoSpies, stable, flushEffects, settleResource, the DOM/inliner building blocks; registers the Bun adapter and boots a zoneless TestBed
/rxjscreateObservableWithValues + the observable type surface; registers the observable layer
/angularprovideAutoSpy, provideAutoSpyForToken, injectSpy, overrideAutoSpy, overrideComponentProvider, assertNgModuleScopes, setupAngularTestEnv, createDirectiveHost, registerDirectiveMatchers, renderShallow, createWithAutoSpies, stable, flushEffects, settleResource, mockResourceProp, mockSignalProp, registerSignalMatchers, registerResourceMatchers, the TestBed diagnostics
/nestjsprovideAutoSpy, injectSpy(moduleRef, token), NestModuleRef, NestValueProvider
/vueprovideAutoSpy, VueInjectionToken, VueProvideSpy
/react, /svelte— (the core, under a name that reads right in those suites)
/consoleconsoleDebugSpyconsoleWarnSpy, installConsoleSpies, resetConsoleSpies, restoreConsole
/zoneinstallProxyZonePatch — and installs it on import. The only entry that touches zones; zone.js is a devDependency of this package and nothing else, and no other entry reaches this module
/setupsetupAutoSpy, setupFakeTimers, advanceTimers, mockSystemTime, withSystemTime, mockNow, useCountingClock, registerFocusMatchers, blockNetwork, guardGlobalPatches, installPerTest, restoreTimerGlobals, the stray-timer and stray-rejection trackers, the mock-registry trackers, describeDuplicateCopies, getPackageCopies
/eslint-pluginthe flat-config plugin object

The core itself also carries, beyond the factories: captureArg, asInstances, narrow, withOverrides, compareTestRuns, mockConstructor, stubConstructor, stubAbortController, stubMediaElement, flushEventLoop, flushEventLoopUntil, settleDynamicImport, assertMocked, moduleNamespace, diffByField, autoMocked, the observer stubs (stubIntersectionObserver / stubResizeObserver / stubMutationObserver / stubObserver) and their entry builders (intersectionEntry, mutationRecord, resizeEntry).

One adapter per run

Each entry registers its mock adapter on import. Import the one that matches your runner — pulling vitest-auto-spy into a bun test run leaves Vitest's adapter installed.

Two helpers are Vitest-only and deliberately absent from /bun-angular, because they need the runner's expect.extend and suite-level hooks: registerSignalMatchers / registerResourceMatchers and the TestBed diagnostics family. mockResourceProp is Vitest-only for a different reason — it lives beside the other mock*Prop helpers, which /bun-angular does not re-export either.

Released under the MIT License.