Modern mock implementations of core Backstage APIs with consistent patterns across all API types. The mockApis namespace provides three usage patterns for each API: fake implementations, factory creators, and Jest mock instances.
The modern approach to API mocking in Backstage tests, providing consistent patterns across all core APIs.
/**
* Modern mock API implementations with three usage patterns:
* 1. Direct fake implementation: mockApis.config()
* 2. Factory creator: mockApis.config.factory()
* 3. Jest mock instance: mockApis.config.mock()
*/
declare const mockApis: {
analytics(): AnalyticsApi;
analytics.factory(): ApiFactory<AnalyticsApi, AnalyticsApi, {}>;
analytics.mock(partialImpl?: Partial<AnalyticsApi>): ApiMock<AnalyticsApi>;
config(options?: { data?: JsonObject }): ConfigApi;
config.factory(): ApiFactory<ConfigApi, ConfigApi, {}>;
config.mock(): ApiMock<ConfigApi>;
discovery(options?: { baseUrl?: string }): DiscoveryApi;
discovery.factory(): ApiFactory<DiscoveryApi, DiscoveryApi, {}>;
discovery.mock(): ApiMock<DiscoveryApi>;
identity(options?: IdentityOptions): IdentityApi;
identity.factory(): ApiFactory<IdentityApi, IdentityApi, {}>;
identity.mock(): ApiMock<IdentityApi>;
permission(options?: PermissionOptions): PermissionApi;
permission.factory(): ApiFactory<PermissionApi, PermissionApi, {}>;
permission.mock(): ApiMock<PermissionApi>;
storage(options?: { data?: JsonObject }): StorageApi;
storage.factory(): ApiFactory<StorageApi, StorageApi, {}>;
storage.mock(): ApiMock<StorageApi>;
translation(): TranslationApi;
translation.factory(): ApiFactory<TranslationApi, TranslationApi, {}>;
translation.mock(): ApiMock<TranslationApi>;
};
type ApiMock<TApi> = {
factory: ApiFactory<TApi, TApi, {}>;
} & { [K in keyof TApi]: jest.MockedFunction<TApi[K]> };Usage Examples:
import { mockApis, TestApiProvider } from "@backstage/test-utils";
// 1. Fake implementation with data
const configApi = mockApis.config({
data: { app: { title: 'Test App' } }
});
// 2. Factory for TestApiProvider
<TestApiProvider apis={[[configApiRef, mockApis.config.factory()]]}>
<MyComponent />
</TestApiProvider>
// 3. Jest mock for testing interactions
const mockConfig = mockApis.config.mock();
mockConfig.getString.mockReturnValue('test-value');Mock implementation for capturing and verifying analytics events.
/**
* Create mock analytics API that captures events for verification
* @returns AnalyticsApi implementation that stores captured events
*/
function analytics(): AnalyticsApi;
/**
* Create analytics API factory for TestApiProvider usage
* @returns ApiFactory for analytics API
*/
function analytics.factory(): ApiFactory<AnalyticsApi, AnalyticsApi, {}>;
/**
* Create Jest mock analytics API with configurable behavior
* @param partialImpl - Partial implementation to override mock behavior
* @returns Jest mock instance with analytics API methods
*/
function analytics.mock(partialImpl?: Partial<AnalyticsApi>): ApiMock<AnalyticsApi>;Mock implementation for Backstage configuration with customizable data.
/**
* Create mock config API with optional data
* @param options - Configuration options
* @param options.data - JSON object representing config data
* @returns ConfigApi implementation backed by provided data
*/
function config(options?: { data?: JsonObject }): ConfigApi;
/**
* Create config API factory for TestApiProvider usage
* @returns ApiFactory for config API
*/
function config.factory(): ApiFactory<ConfigApi, ConfigApi, {}>;
/**
* Create Jest mock config API
* @returns Jest mock instance with all ConfigApi methods
*/
function config.mock(): ApiMock<ConfigApi>;Mock implementation for Backstage service discovery.
/**
* Create mock discovery API with configurable base URL
* @param options - Discovery options
* @param options.baseUrl - Base URL for all discovered services
* @returns DiscoveryApi implementation
*/
function discovery(options?: { baseUrl?: string }): DiscoveryApi;
/**
* Create discovery API factory for TestApiProvider usage
* @returns ApiFactory for discovery API
*/
function discovery.factory(): ApiFactory<DiscoveryApi, DiscoveryApi, {}>;
/**
* Create Jest mock discovery API
* @returns Jest mock instance with discovery API methods
*/
function discovery.mock(): ApiMock<DiscoveryApi>;Mock implementation for Backstage user identity.
/**
* Create mock identity API with user information
* @param options - Identity configuration
* @param options.userEntityRef - User entity reference
* @param options.ownershipEntityRefs - Owned entity references
* @returns IdentityApi implementation with mock user data
*/
function identity(options?: IdentityOptions): IdentityApi;
/**
* Create identity API factory for TestApiProvider usage
* @returns ApiFactory for identity API
*/
function identity.factory(): ApiFactory<IdentityApi, IdentityApi, {}>;
/**
* Create Jest mock identity API
* @returns Jest mock instance with identity API methods
*/
function identity.mock(): ApiMock<IdentityApi>;
interface IdentityOptions {
userEntityRef?: string;
ownershipEntityRefs?: string[];
token?: string;
email?: string;
displayName?: string;
picture?: string;
}Mock implementation for Backstage authorization and permissions.
/**
* Create mock permission API with configurable authorization behavior
* @param options - Permission configuration
* @param options.allow - Default allow/deny behavior for all permissions
* @param options.requestHandler - Custom handler for permission requests
* @returns PermissionApi implementation
*/
function permission(options?: PermissionOptions): PermissionApi;
/**
* Create permission API factory for TestApiProvider usage
* @returns ApiFactory for permission API
*/
function permission.factory(): ApiFactory<PermissionApi, PermissionApi, {}>;
/**
* Create Jest mock permission API
* @returns Jest mock instance with permission API methods
*/
function permission.mock(): ApiMock<PermissionApi>;
interface PermissionOptions {
authorize?:
| AuthorizeResult.ALLOW
| AuthorizeResult.DENY
| ((request: EvaluatePermissionRequest) => AuthorizeResult.ALLOW | AuthorizeResult.DENY);
}Mock implementation for Backstage browser storage.
/**
* Create mock storage API with optional initial data
* @param options - Storage configuration
* @param options.data - Initial data for the storage backend
* @returns StorageApi implementation backed by in-memory storage
*/
function storage(options?: { data?: JsonObject }): StorageApi;
/**
* Create storage API factory for TestApiProvider usage
* @returns ApiFactory for storage API
*/
function storage.factory(): ApiFactory<StorageApi, StorageApi, {}>;
/**
* Create Jest mock storage API
* @returns Jest mock instance with storage API methods
*/
function storage.mock(): ApiMock<StorageApi>;Mock implementation for Backstage internationalization.
/**
* Create mock translation API
* @returns TranslationApi implementation for testing i18n functionality
*/
function translation(): TranslationApi;
/**
* Create translation API factory for TestApiProvider usage
* @returns ApiFactory for translation API
*/
function translation.factory(): ApiFactory<TranslationApi, TranslationApi, {}>;
/**
* Create Jest mock translation API
* @returns Jest mock instance with translation API methods
*/
function translation.mock(): ApiMock<TranslationApi>;These individual mock classes are deprecated in favor of the mockApis namespace but remain available for backward compatibility.
/**
* @deprecated Use mockApis.config() instead
* Thin wrapper around ConfigReader for mocking configuration
*/
class MockConfigApi implements ConfigApi {
constructor(data: JsonObject);
has(key: string): boolean;
keys(): string[];
get<T>(key?: string): T;
getOptional<T>(key?: string): T | undefined;
getConfig(key: string): Config;
getOptionalConfig(key: string): Config | undefined;
getConfigArray(key: string): Config[];
getOptionalConfigArray(key: string): Config[] | undefined;
getNumber(key: string): number;
getOptionalNumber(key: string): number | undefined;
getBoolean(key: string): boolean;
getOptionalBoolean(key: string): boolean | undefined;
getString(key: string): string;
getOptionalString(key: string): string | undefined;
getStringArray(key: string): string[];
getOptionalStringArray(key: string): string[] | undefined;
}/**
* Mock implementation of ErrorApi for testing error handling
*/
class MockErrorApi implements ErrorApi {
constructor(options?: MockErrorApiOptions);
post(error: ErrorApiError, context?: ErrorApiErrorContext): void;
error$(): Observable<{error: ErrorApiError; context?: ErrorApiErrorContext}>;
getErrors(): ErrorWithContext[];
waitForError(pattern: RegExp, timeoutMs?: number): Promise<ErrorWithContext>;
}
interface MockErrorApiOptions {
collect?: boolean;
}
interface ErrorWithContext {
error: ErrorApiError;
context?: ErrorApiErrorContext;
}/**
* Test helper implementation of FetchApi with configurable behavior
*/
class MockFetchApi implements FetchApi {
constructor(options?: MockFetchApiOptions);
readonly fetch: typeof crossFetch;
}
interface MockFetchApiOptions {
baseImplementation?: undefined | 'none' | typeof crossFetch;
resolvePluginProtocol?: undefined | {
discoveryApi: Pick<DiscoveryApi, 'getBaseUrl'>
};
injectIdentityAuth?: undefined |
{ token: string } |
{ identityApi: Pick<IdentityApi, 'getCredentials'> };
}type JsonObject = { [key: string]: any };
interface ApiFactory<TApi, TImpl extends TApi, TDeps extends {}> {
api: ApiRef<TApi>;
deps: { [key in keyof TDeps]: ApiRef<TDeps[key]> };
factory(deps: TDeps): TImpl;
}