UnitReference

The UnitReference object provides access to mocked dependencies within the test environment. It’s returned by both TestBed.solitary() and TestBed.sociable() after compilation.

Interface

interface UnitReference {
get<T>(token: InjectableIdentifier<T>, metadata?: IdentifierMetadata): Mocked<T>;
}

InjectableIdentifier<T> comes from @suites/types.di and includes tokens registered by the selected DI adapter. The signatures above and below summarize the public overloads.

Method

.get()

Retrieves a mocked instance of a dependency.

Signature

get<T>(token: InjectableIdentifier<T>, metadata?: IdentifierMetadata): Mocked<T>

Parameters

ParameterTypeDescription
tokenInjectableIdentifier<T>A class, string, symbol, or adapter-registered token
metadataIdentifierMetadataInversify named/tagged metadata; omit for NestJS and InjectionJS

Returns

Returns a Mocked<T> instance with all methods replaced by stubs.

Examples

Basic Usage

const { unit, unitRef } = await TestBed.solitary(UserService).compile();
// Get mocked dependencies
const database = unitRef.get(Database);
const logger = unitRef.get(Logger);
// Configure mock behavior
database.findUser.mockResolvedValue({ id: 1, name: 'John' });
logger.log.mockReturnValue(undefined);

Using with Class Constructors

// NestJS example
@Injectable()
class OrderService {
constructor(
private inventory: InventoryService,
private payment: PaymentService
) {}
}
const { unitRef } = await TestBed.solitary(OrderService).compile();
const inventory = unitRef.get(InventoryService);
const payment = unitRef.get(PaymentService);

Using with Injection Tokens

const TYPES = {
Database: Symbol.for('Database'),
Logger: Symbol.for('Logger'),
Cache: Symbol.for('Cache')
};
@injectable()
class DataService {
constructor(
@inject(TYPES.Database) private db: Database,
@inject(TYPES.Logger) private logger: Logger,
@inject(TYPES.Cache) private cache: Cache
) {}
}
const { unitRef } = await TestBed.solitary(DataService).compile();
// Use symbols to retrieve mocks
const database = unitRef.get<Database>(TYPES.Database);
const logger = unitRef.get<Logger>(TYPES.Logger);
const cache = unitRef.get<Cache>(TYPES.Cache);

String-based Tokens

// Some frameworks use string tokens
const { unitRef } = await TestBed.solitary(ConfigService).compile();
// Retrieve an automatically mocked token dependency.
const dbConfig = unitRef.get<DatabaseConfig>('DATABASE_CONFIG');

InjectionJS tokens

Load @suites/di.injectionjs/metadata in your test declarations. Using the service and token from the InjectionJS guide:

import { TestBed } from '@suites/unit';
import { USER_REPOSITORY, UserService } from './user.service';
import type { UserRepository } from './user.service';
const { unitRef } = await TestBed.solitary(UserService).compile();
const repository = unitRef.get<UserRepository>(USER_REPOSITORY);
repository.findName.mockResolvedValue('Alice');

Pass the original token instance. Creating another new InjectionToken('UserRepository') does not identify the same dependency, even when the descriptions match. Omit the metadata argument for InjectionJS.

Named and tagged dependencies (Inversify)

Load @suites/di.inversify/metadata in your declarations, then pass the metadata used by the injection:

const repository = unitRef.get(Repository, { named: 'primary' });

With @suites/di.nestjs/metadata, the metadata type is never; NestJS calls take only a class or token. See Types.

Important Limitations

Injection and retrieval are separate: a dependency can be injected into unit without being available through unitRef.get().

Injected dependencies and retrievable mocks The real unit receives auto mocks, .impl() mocks, supplied .final() values, and exposed real classes. unitRef.get() can look up only auto mocks and .impl() mocks. Exposed classes apply to sociable tests. 1. Injected into the unit unit Real class Auto mock .impl() mock .final() supplied .expose() real 2. Available through lookup unitRef.get() Auto mock .impl() mock No lookup: .final() values or exposed classes.
Solid arrows show injection; dotted arrows show lookup. Dashed boxes are configurable mocks. Exposed real classes apply to sociable tests.

Cannot Retrieve Exposed Classes in Sociable Tests

When using TestBed.sociable() with .expose(), exposed classes are treated as real implementations, not mocks. Because unitRef is designed exclusively for accessing mocked dependencies, you cannot retrieve a real instance from it.

const { unitRef } = await TestBed.sociable(PaymentService)
.expose(TaxCalculator) // Real implementation
.compile();
// ❌ This will throw an error because TaxCalculator is a real instance
const calculator = unitRef.get(TaxCalculator);
// ✅ Only non-exposed (mocked) dependencies can be retrieved
const database = unitRef.get(Database);

Cannot Retrieve Dependencies with .mock().final()

Dependencies configured with .mock().final() are injected as supplied and cannot be retrieved via unitRef. Suites does not freeze the supplied object. If you need to retrieve and configure a mock during your tests, use .mock().impl() instead.

const { unitRef } = await TestBed.solitary(UserService)
.mock(Database)
.final({ find: async () => [] }) // Supplied implementation
.compile();
// ❌ This will throw an error because the mock is final
const database = unitRef.get(Database);

Type Safety

The Mocked<T> type ensures type safety for your mocks (See more in Types Reference:

interface UserRepository {
findById(id: string): Promise<User>;
save(user: User): Promise<User>;
delete(id: string): Promise<void>;
}
const userRepo = unitRef.get<UserRepository>('USER_REPOSITORY'); // Match the injected token
// ✅ TypeScript knows these methods exist
userRepo.findById.mockResolvedValue(testUser);
userRepo.save.mockResolvedValue(testUser);
userRepo.delete.mockResolvedValue(undefined);
// ❌ TypeScript error: Property 'invalid' does not exist
userRepo.invalid.mockResolvedValue(null);

Common Errors

”Cannot retrieve exposed dependency"

// Problem: Trying to get an exposed class
const { unitRef } = await TestBed.sociable(Service)
.expose(RealDependency)
.compile();
const dep = unitRef.get(RealDependency); // ❌ Error
// Solution: Only get non-exposed dependencies

"Cannot retrieve final mock"

// Problem: Trying to get a .final() mock
const { unitRef } = await TestBed.solitary(Service)
.mock(Database)
.final({ find: async () => [] })
.compile();
const db = unitRef.get(Database); // ❌ Error
// Solution: Use .impl() instead if you need to retrieve the mock

"Token not found”

// Problem: Using wrong token
const logger = unitRef.get('LoggerToken'); // ❌ String doesn't match
// Solution: Use the exact token used in injection
const logger = unitRef.get(LoggerService); // ✅ Correct class
// or
const logger = unitRef.get<Logger>('LoggerToken'); // ✅ Correct string token

See Also