Skip to content

Commit

Permalink
refactor(core): dependencies mocker to return new interface
Browse files Browse the repository at this point in the history
  • Loading branch information
omermorad committed Jul 1, 2023
1 parent 8c5c6cb commit 0881c0e
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 29 deletions.
27 changes: 17 additions & 10 deletions packages/core/__test__/testbed-builder.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
DependencyTwo,
DependencyFive,
} from './integration.assets';
import { PrimitiveValue } from '@automock/common';
import { DependenciesReflector } from '@automock/common';

describe('Builder Factory Integration Test', () => {
let underTest: TestBedBuilder<MainClass>;
Expand All @@ -18,16 +18,22 @@ describe('Builder Factory Integration Test', () => {
const mockFunctionMockOfBuilder = jest.fn(() => '__MOCKED_FROM_BUILDER__');
const mockFunctionMockOfMocker = jest.fn(() => '__MOCKED_FROM_MOCKER__');

const reflectorMock = {
const reflectorMock: DependenciesReflector = {
reflectDependencies: () => {
return new Map<Type | string, Type | PrimitiveValue>([
[DependencyOne, DependencyOne],
[DependencyTwo, DependencyTwo],
[DependencyThree, DependencyThree],
['DEPENDENCY_FOUR_TOKEN', DependencyFourToken],
[DependencyFive, DependencyFive],
['STRING_TOKEN', 'ANY STRING'],
]);
return {
constructor: [
[DependencyOne, DependencyOne],
// Repeat on the same dependency twice, as it can be returned from the reflector (@since 1.2.2)
[DependencyTwo, DependencyTwo],
[DependencyTwo, DependencyTwo],
[DependencyThree, DependencyThree],
// Repeat on the same dependency twice, as it can be returned from the reflector (@since 1.2.2)
['DEPENDENCY_FOUR_TOKEN', DependencyFourToken],
['DEPENDENCY_FOUR_TOKEN', DependencyFourToken],
[DependencyFive, DependencyFive],
['STRING_TOKEN', 'ANY STRING'],
],
};
},
};

Expand Down Expand Up @@ -76,6 +82,7 @@ describe('Builder Factory Integration Test', () => {
it.each([
[DependencyOne.name, '__MOCKED_FROM_BUILDER__', DependencyOne],
[DependencyTwo.name, '__MOCKED_FROM_BUILDER__', DependencyTwo],
[DependencyTwo.name, '__MOCKED_FROM_BUILDER__', DependencyTwo],
[DependencyThree.name, '__MOCKED_FROM_MOCKER__', DependencyThree],
['custom token with function', '__MOCKED_FROM_BUILDER__', 'DEPENDENCY_FOUR_TOKEN'],
[DependencyFive.name, '__MOCKED_FROM_MOCKER__', DependencyFive],
Expand Down
45 changes: 33 additions & 12 deletions packages/core/src/services/dependencies-mocker.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { DependenciesMocker } from './dependencies-mocker';
import { Type } from '@automock/types';
import { DependenciesReflector } from '@automock/common';
import { DependenciesMocker, MockedDependencies } from './dependencies-mocker';

import MockedFn = jest.MockedFn;
import { StubbedInstance, Type } from '@automock/types';

class SomeClassOne {}

Expand All @@ -11,40 +14,58 @@ const MOCKED = '__MOCKED__';
describe('Dependencies Mocker Unit Spec', () => {
let underTest: DependenciesMocker;
const mockFunctionStub = () => MOCKED;
const reflectorMock = { reflectDependencies: jest.fn() };
const reflectorMock = {
reflectDependencies: jest.fn() as MockedFn<DependenciesReflector['reflectDependencies']>,
};

beforeAll(() => {
underTest = new DependenciesMocker(reflectorMock, mockFunctionStub);
});

describe('mocking all class dependencies', () => {
beforeAll(() => {
reflectorMock.reflectDependencies.mockReturnValue(
new Map<Type | string, Type>([
reflectorMock.reflectDependencies.mockReturnValue({
constructor: [
[SomeClassOne, SomeClassOne],
[SomeClassTwo, SomeClassTwo],
[SomeClassTwo, SomeClassTwo],
['TOKEN', ClassFromToken],
])
);
],
});
});

describe('assuming there is only one mocked class in the given dependencies', () => {
class DoesntMatterClass {}
let result: MockedDependencies;

class ArbitraryClass {}
const alreadyMockedDependencies = new Map<Type | string, Type>([
[SomeClassTwo, SomeClassTwoMockedLike],
]);

it('should return a map of class dependencies and mock anything not mocked', () => {
const result = underTest.mockAllDependencies(DoesntMatterClass)(alreadyMockedDependencies);
beforeAll(() => {
result = underTest.mockAllDependencies(ArbitraryClass)(alreadyMockedDependencies);
});

expect(result).toEqual(
new Map<Type | string, Type | string>([
it('should return a map of the mocks of the class dependencies', () => {
expect(result.mocks).toEqual<MockedDependencies['mocks']>(
new Map<Type | string, StubbedInstance<unknown>>([
[SomeClassOne, MOCKED],
[SomeClassTwo, SomeClassTwoMockedLike],
['TOKEN', MOCKED],
])
);
});

it('should also return the original reflected dependencies', () => {
expect(result.origin).toEqual<MockedDependencies['origin']>({
constructor: [
[SomeClassOne, SomeClassOne],
[SomeClassTwo, SomeClassTwo],
[SomeClassTwo, SomeClassTwo],
['TOKEN', ClassFromToken],
],
});
});
});
});
});
19 changes: 15 additions & 4 deletions packages/core/src/services/dependencies-mocker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { Type, MockFunction, StubbedInstance } from '@automock/types';
import { DependenciesReflector, PrimitiveValue } from '@automock/common';
import { ClassDependenciesMap } from '@automock/common/src';

export interface MockedDependencies {
mocks: Map<Type | string, StubbedInstance<unknown>>;
origin: ClassDependenciesMap;
}

export class DependenciesMocker {
public constructor(
Expand All @@ -17,12 +23,14 @@ export class DependenciesMocker {
targetClass: Type<TClass>
): (
alreadyMockedDependencies: Map<Type | string, StubbedInstance<unknown> | PrimitiveValue>
) => Map<Type | string, StubbedInstance<unknown>> {
return (alreadyMockedDependencies: Map<Type | string, StubbedInstance<unknown>>) => {
) => MockedDependencies {
return (
alreadyMockedDependencies: Map<Type | string, StubbedInstance<unknown>>
): MockedDependencies => {
const classDependencies = this.reflector.reflectDependencies(targetClass);
const classMockedDependencies = new Map<Type | string, StubbedInstance<unknown>>();

for (const [dependency] of classDependencies.entries()) {
for (const [dependency] of classDependencies.constructor) {
const alreadyMocked = alreadyMockedDependencies.get(dependency);

const mockedDependency = alreadyMocked
Expand All @@ -32,7 +40,10 @@ export class DependenciesMocker {
classMockedDependencies.set(dependency, mockedDependency);
}

return classMockedDependencies;
return {
mocks: classMockedDependencies,
origin: classDependencies,
};
};
}
}
6 changes: 3 additions & 3 deletions packages/core/src/services/testbed-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,14 @@ export class BuilderFactory {
};
},
compile(): UnitTestBed<TClass> {
const allDependenciesMocked =
const { mocks, origin } =
instance.dependenciesMocker.mockAllDependencies(targetClass)(dependenciesToOverride);

const values = Array.from(allDependenciesMocked.values());
const values = origin.constructor.map(([dependency]) => mocks.get(dependency));

return {
unit: new targetClass(...values) as TClass,
unitRef: new UnitReference(allDependenciesMocked),
unitRef: new UnitReference(mocks),
};
},
};
Expand Down

0 comments on commit 0881c0e

Please sign in to comment.