Add tracingServiceMock test util

Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
Eric Peterson
2026-04-28 17:25:34 +02:00
parent 130db0d6c6
commit 7fb12b83c2
5 changed files with 128 additions and 0 deletions
@@ -0,0 +1,5 @@
---
'@backstage/backend-test-utils': patch
---
Added a new tracing service mock to be leveraged in tests
@@ -14,6 +14,10 @@ import { JsonValue } from '@backstage/types';
import { LoggerService } from '@backstage/backend-plugin-api';
import { MetricsService } from '@backstage/backend-plugin-api/alpha';
import { ServiceFactory } from '@backstage/backend-plugin-api';
import { TracingService } from '@backstage/backend-plugin-api/alpha';
import { TracingServiceAttributeValue } from '@backstage/backend-plugin-api/alpha';
import { TracingServiceSpan } from '@backstage/backend-plugin-api/alpha';
import { TracingServiceSpanStatus } from '@backstage/backend-plugin-api/alpha';
// @alpha (undocumented)
export function actionsRegistryServiceMock(options?: {
@@ -81,6 +85,14 @@ export class MockActionsRegistry
>(options: ActionsRegistryActionOptions<TInputSchema, TOutputSchema>): void;
}
// @alpha
export interface MockedTracingServiceSpan extends TracingServiceSpan {
// (undocumented)
setAttribute: jest.Mock<void, [string, TracingServiceAttributeValue]>;
// (undocumented)
setStatus: jest.Mock<void, [TracingServiceSpanStatus]>;
}
// @public (undocumented)
export type ServiceMock<TService> = {
factory: ServiceFactory<TService>;
@@ -92,5 +104,20 @@ export type ServiceMock<TService> = {
: TService[Key];
};
// @alpha
export interface TracingServiceMock extends TracingService {
// (undocumented)
factory: ServiceFactory<TracingService>;
spans: MockedTracingServiceSpan[];
// (undocumented)
startActiveSpan: jest.MockedFunction<TracingService['startActiveSpan']>;
}
// @alpha (undocumented)
export namespace tracingServiceMock {
const factory: () => ServiceFactory<TracingService, 'plugin', 'singleton'>;
const mock: () => TracingServiceMock;
}
// (No @packageDocumentation comment for this package)
```
@@ -0,0 +1,89 @@
/*
* Copyright 2026 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
createServiceFactory,
ServiceFactory,
} from '@backstage/backend-plugin-api';
import {
TracingService,
TracingServiceAttributeValue,
TracingServiceSpan,
TracingServiceSpanStatus,
tracingServiceRef,
} from '@backstage/backend-plugin-api/alpha';
import { tracingServiceFactory } from '@backstage/backend-defaults/alpha';
/**
* A jest-mocked span captured by {@link TracingServiceMock}.
*
* @alpha
*/
export interface MockedTracingServiceSpan extends TracingServiceSpan {
setAttribute: jest.Mock<void, [string, TracingServiceAttributeValue]>;
setStatus: jest.Mock<void, [TracingServiceSpanStatus]>;
}
/**
* Mock for the `TracingService`. Captures every span created via
* `startActiveSpan` so tests can assert on the options passed in and the
* methods called on the span inside the callback.
*
* @alpha
*/
export interface TracingServiceMock extends TracingService {
startActiveSpan: jest.MockedFunction<TracingService['startActiveSpan']>;
/** Spans created by `startActiveSpan` calls, in order. */
spans: MockedTracingServiceSpan[];
factory: ServiceFactory<TracingService>;
}
/**
* @alpha
*/
export namespace tracingServiceMock {
/**
* Returns the real `tracingServiceFactory` from `@backstage/backend-defaults`,
* for tests that want the full default implementation.
*/
export const factory = () => tracingServiceFactory;
/**
* Builds a mock `TracingService` backed by jest mocks.
*/
export const mock = (): TracingServiceMock => {
const spans: MockedTracingServiceSpan[] = [];
const startActiveSpan = jest.fn(async (_name, fn, _options) => {
const span: MockedTracingServiceSpan = {
setAttribute: jest.fn(),
setStatus: jest.fn(),
};
spans.push(span);
return await fn(span);
}) as TracingServiceMock['startActiveSpan'];
const service: TracingService = { startActiveSpan };
return Object.assign(service as TracingServiceMock, {
spans,
factory: createServiceFactory({
service: tracingServiceRef,
deps: {},
factory: () => service,
}),
});
};
}
@@ -18,4 +18,9 @@ export { actionsRegistryServiceMock } from './ActionsRegistryServiceMock';
export { MockActionsRegistry } from './MockActionsRegistry';
export { actionsServiceMock } from './ActionsServiceMock';
export { metricsServiceMock } from './MetricsServiceMock';
export {
tracingServiceMock,
type TracingServiceMock,
type MockedTracingServiceSpan,
} from './TracingServiceMock';
export { type ServiceMock } from './alphaCreateServiceMock';
@@ -44,6 +44,7 @@ import {
actionsRegistryServiceMock,
actionsServiceMock,
metricsServiceMock,
tracingServiceMock,
} from '../alpha/services';
/** @public */
@@ -94,6 +95,7 @@ export const defaultServiceFactories = [
actionsRegistryServiceMock.factory(),
actionsServiceMock.factory(),
metricsServiceMock.factory(),
tracingServiceMock.factory(),
];
/**