Running jasmine tests for a component with NgZone dependency
Asked Answered
A

5

11

How would I go ahead with running a jasmine test for the following component:

@Component({
  moduleId: module.id,
  selector: "testComp",
  template: "<div>{{value}}</div>",
})
export class TestComp {
  public value: string = "This is me";
  constructor(public zone: NgZone) {
    this.zone.run(() => console.log("zone is here"));
  }
}

The following fails with the Can't resolve all parameters for NgZone:

describe("test", () => {
    let fixture;
    let component;

beforeEach(async(() => {
    TestBed.configureTestingModule({
        declarations: [TestComp],
        schemas: [NO_ERRORS_SCHEMA],
        providers: [NgZone]
    }).compileComponents;
}));
beforeEach(() => {
    fixture = TestBed.createComponent(TestComp);
    component = fixture.debugElement.componentInstance;
});
it("should check that the component is created", () => {
    expect(component).toBeTruthy();
});

})

using Angular 4.1.3. I found the MockNgZone class @ https://no-shadow-angular-io.firebaseapp.com/docs/ts/latest/api/core/testing/MockNgZone-class.html. But it seems unavailable in the @angular/core/testing for this particular version: enter image description here

Anybody knows what I should do to test this component?

Regards

Alinealinna answered 27/11, 2017 at 2:13 Comment(0)
K
14

If your problem is about runOutsideAngular because then you cannot use async or fakeAsync, the only thing you need to mock is that function and the following works well:

const ngZone = TestBed.get(NgZone);

spyOn(ngZone, 'runOutsideAngular').and.callFake((fn: Function) => fn());
Kaminsky answered 17/5, 2018 at 16:38 Comment(0)
R
11

In Angular 5.2.4 (installed via Angular CLI 1.6.8) the mock was removed from the codebase so there's no need to use it in Jasmine. Just skip the declaration of NgZone in providers list.

Robers answered 4/3, 2018 at 6:46 Comment(1)
I was getting many errors until I removed the NgZone from the providers. Thanks!Dehiscence
P
7

It's a bit of a mystery, MockNgZone is still in the source but removed from the public API.

Given the simple implementation of mock run()

export class MockNgZone extends NgZone {
  ...
  run(fn: Function): any { return fn(); }

I would use this to get you over the hump

const mockNgZone = jasmine.createSpyObj('mockNgZone', ['run', 'runOutsideAngular']);
mockNgZone.run.and.callFake(fn => fn());

TestBed.configureTestingModule({
  ...
  providers: [
    { provide: NgZone, useValue: mockNgZone },
  ]
Plenteous answered 3/12, 2017 at 2:29 Comment(1)
I'm getting TypeError: Cannot read property 'subscribe' of undefinedNuthatch
B
6

I also had similar requirement and this is how I did it,

TestBed configuration,

beforeEach(() => {
    TestBed.configureTestingModule({
        imports: [
            // Specify imports
        ],
        providers: [
            { provide: DependentService, useValue: dependentServiceSpy }
            // Do not provide NgZone here
        ]
    });
    guard = TestBed.inject(ARouteGuard);
});

Please note here that I HAVE NOT SPECIFIED NgZone in the providers array.

And this is how my tests will look like,

it('should be created', () => {
    let zone = TestBed.get(NgZone);
    spyOn(zone, 'run').and.callFake((fn: Function) => fn());
    
    // Implement your test and expectations

    expect(guard).toBeTruthy();
});

I had to remove NgZone or it's corresponding mock objects from the providers: [ ] array because, it introduced other errors like "Can't resolve all parameters for NgZone" and "Cannot read property subscribe of undefined".

Boa answered 12/8, 2020 at 17:28 Comment(0)
R
0

We had the same issue, exactly. At the end we left ngZone as is, and make sure we test the callbacks it uses.

beforeEach(async(() => {
TestBed.configureTestingModule({
    ...
    providers: [NgZone]
  })
}));

And for code that used the ngZone such as

zone.run(someFunction)

We made sure to have good test coverage someFunction with unit tests.

Rosettarosette answered 27/11, 2017 at 6:45 Comment(2)
how do you test someFunction if the check component test is already failing? I have the same issue than AndreyIdiot
Make it a pure function at a regular js module. Write tests for the module. Import it into the component.Rosettarosette

© 2022 - 2024 — McMap. All rights reserved.