Skip to content

Commit

Permalink
Merge pull request #4502 from satanTime/issues/4367
Browse files Browse the repository at this point in the history
feat(MockInstance): ignores undefined properties #4367
  • Loading branch information
satanTime authored Dec 11, 2022
2 parents 7dfd1b7 + 70d9781 commit 76a7f80
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 0 deletions.
3 changes: 3 additions & 0 deletions libs/ng-mocks/src/lib/mock-helper/mock-helper.stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export default <T = MockedFunction>(instance: any, override: any, style?: 'get'

for (const key of Object.getOwnPropertyNames(applyOverrides)) {
const desc = skipProps.indexOf(key) === -1 ? Object.getOwnPropertyDescriptor(applyOverrides, key) : undefined;
if (desc && Object.prototype.hasOwnProperty.call(desc, 'value') && desc.value === undefined) {
continue;
}
helperMockService.definePropertyDescriptor(correctInstance, key, desc);
}

Expand Down
125 changes: 125 additions & 0 deletions tests/issue-4367/test.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { Component, Injectable, NgModule } from '@angular/core';
import { TestBed } from '@angular/core/testing';

import {
MockBuilder,
MockInstance,
MockProvider,
MockRender,
} from 'ng-mocks';

@Injectable()
class TargetService {
public method1() {
return `${this.constructor.name}:method1:real`;
}

public method2() {
return `${this.constructor.name}:method2:real`;
}
}

@Component({
selector: 'target',
template: '',
})
class TargetComponent {
constructor(public readonly service: TargetService) {}
}

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

// @see https://github.com/help-me-mom/ng-mocks/issues/4367
describe('issue-4367', () => {
describe('MockProvider', () => {
beforeEach(() =>
TestBed.configureTestingModule({
declarations: [TargetComponent],
providers: [
MockProvider(TargetService, {
method1: () => 'mock',
method2: undefined, // <- should be default spy
}),
],
}),
);

it('overrides method1 only', () => {
const fixture = MockRender(TargetComponent);

// method2 should be default mock
expect(
fixture.point.componentInstance.service.method1,
).toBeDefined();
expect(
fixture.point.componentInstance.service.method2,
).toBeDefined();
});
});

describe('MockBuilder', () => {
beforeEach(() =>
MockBuilder(TargetComponent, TargetModule).mock(TargetService, {
method1: () => 'mock',
method2: undefined, // <- should be default spy
}),
);

it('overrides method1 only', () => {
const fixture = MockRender(TargetComponent);

// method2 should be default mock
expect(
fixture.point.componentInstance.service.method1,
).toBeDefined();
expect(
fixture.point.componentInstance.service.method2,
).toBeDefined();
});
});

describe('MockInstance', () => {
MockInstance.scope();
beforeEach(() =>
TestBed.configureTestingModule({
declarations: [TargetComponent],
providers: [MockProvider(TargetService)],
}),
);

it('overrides method1 only', () => {
MockInstance(TargetService, () => ({
method1: () => 'mock',
method2: undefined, // <- should be default spy
}));
const fixture = MockRender(TargetComponent);

// method2 should be default mock
expect(
fixture.point.componentInstance.service.method1,
).toBeDefined();
expect(
fixture.point.componentInstance.service.method2,
).toBeDefined();
});

it('overrides method1 and method2', () => {
MockInstance(TargetService, 'method1', () => 'mock');
MockInstance(TargetService, 'method2', undefined as never); // <- breaks the things
const fixture = MockRender(TargetComponent);

// method2 should be undefined
expect(
fixture.point.componentInstance.service.method1,
).toBeDefined();
expect(
fixture.point.componentInstance.service.method2,
).not.toBeDefined();
});
});
});

0 comments on commit 76a7f80

Please sign in to comment.