Skip to content

Commit

Permalink
Throws error with a more helpful message if a provider object is pass…
Browse files Browse the repository at this point in the history
…ed to `keep` or `mock`.
  • Loading branch information
ajlouie committed Sep 14, 2024
1 parent 4bef58f commit 2b65713
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 6 deletions.
26 changes: 20 additions & 6 deletions libs/ng-mocks/src/lib/mock-builder/promise/init-ng-modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,26 @@ export default ({ configDefault, keepDef, mockDef, replaceDef }: BuilderData, de
continue;
}

const errorMessage = [
`MockBuilder has found a missing dependency: ${funcGetName(def)}.`,
'It means no module provides it.',
'Please, use the "export" flag if you want to add it explicitly.',
'https://ng-mocks.sudo.eu/api/MockBuilder#export-flag',
].join(' ');
const depName = funcGetName(def);
const errorMessages = ['Error:'];
const defStr = ngMocksUniverse.getResolution(def);

if (depName === 'Object') {
errorMessages.push(
`A provider object has been incorrectly passed to the`,
`MockerBuilder ${defStr}() method. Did you mean to use`,
`MockerBuilder.provide()?`,
);
} else {
errorMessages.push(
`MockBuilder has found a missing dependency: ${depName}.`,
'It means no module provides it.',
'Please, use the "export" flag if you want to add it explicitly.',
'https://ng-mocks.sudo.eu/api/MockBuilder#export-flag',
);
}

const errorMessage = errorMessages.join(' ');

if (globalFlags.onMockBuilderMissingDependency === 'warn') {
console.warn(errorMessage);
Expand Down
108 changes: 108 additions & 0 deletions tests/issue-10020/errors.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { Component, Injectable, NgModule } from '@angular/core';

import { MockBuilder } from 'ng-mocks';

@Injectable()
class RootService {}

@Injectable()
class TargetService {
someAttribute = '';
constructor(public readonly root: RootService) {
this.someAttribute = 'some value';
}
}

@Component({
selector: 'target-10020-errors',
template: 'target',
})
class TargetComponent {
constructor(
public readonly target: TargetService,
public readonly root: RootService,
) {}
}

@NgModule({
declarations: [TargetComponent],
providers: [TargetService],
})
class TargetModule {}

class MockProviderClass {
someAttribute = 'mock class value';
}

const mockProviderValue = {
provide: TargetService,
useValue: { someAttribute: 'mock value' },
};
const mockProviderClass = {
provide: TargetService,
useClass: MockProviderClass,
};
const expectedMessagePattern =
/A provider object has been incorrectly passed to the MockerBuilder (keep|mock)\(\) method\. Did you mean to use MockerBuilder\.provide\(\)\?/;

describe('issue-10020:errors', () => {
describe('strict', () => {
describe('.keep', () => {
it('throws on using provider value mock with keep', () => {
const builder = MockBuilder(
TargetComponent,
TargetModule,
).keep(mockProviderValue);
expect(() => builder.build()).toThrowError(
expectedMessagePattern,
);
});

it('throws on using provider class mock with keep', () => {
const builder = MockBuilder(
TargetComponent,
TargetModule,
).keep(mockProviderClass);
expect(() => builder.build()).toThrowError(
expectedMessagePattern,
);
});

it('throws on using provider value mock with mock', () => {
const builder = MockBuilder(
TargetComponent,
TargetModule,
).mock(mockProviderValue);
expect(() => builder.build()).toThrowError(
expectedMessagePattern,
);
});

it('throws on using provider class mock with mock', () => {
const builder = MockBuilder(
TargetComponent,
TargetModule,
).mock(mockProviderClass);
expect(() => builder.build()).toThrowError(
expectedMessagePattern,
);
});

it('succeeds on using provider value mock with provide', () => {
const builder = MockBuilder(
TargetComponent,
TargetModule,
).provide(mockProviderValue);
expect(() => builder.build()).not.toThrow();
});

it('succeeds on using provider class mock with provide', () => {
const builder = MockBuilder(
TargetComponent,
TargetModule,
).provide(mockProviderClass);
expect(() => builder.build()).not.toThrow();
});
});
});
});

0 comments on commit 2b65713

Please sign in to comment.