Spec has no expectations - Jasmine testing the callback function
Asked Answered
W

4

30

I have a method which is being called using a d3 timer. Whenever the method is called, the method emits an object with a couple of values. One of the values increases over time. I would like to write a test to check whether the values are in the ascending order or not (i.e., increasing over time or not).

So, to tackle this, In my test, I subscribe to the event emitter and inside the subscription, I am pushing the object which I receive into a local array. And then, I am expecting the array[i] to be less than the array[i+1]. I think my logic is perfectly correct but I am not sure why I am getting an error from Jasmine saying that the spec has no expectations even though I have one.

Here is the code:

let x = d3.timer((elapsed) => { 
    this.method(); // call the function
    if(elapsed >= 500) {
     x.stop(); // stops the timer.
    }
});

method(elapsed) {
 // do something
 if(elapsed > 500) {
   this.output.emit({x: somevalue, y: somevalue, f: increasingvalue });
 }
}

The Jasmine Spec:

it('my spec', inject([JumpService], (service: JumpService) =>{
  array = [];
  //service calls the method
  service.output.subscribe(e => {
   array.push(e);
   // A console statement here will give me the length and the object pushed.
   for(let i = 0; i< array.length - 1; i++) {
    expect(array[i].f).toBeLessThan(array[i+1].f);
   }

  });

}));

Am I doing anything wrong here? How can I tackle such kind of a scenario? Please guide me in a right direction.

Thank you.

Wiegand answered 8/8, 2017 at 22:30 Comment(2)
Just related; I got this error because I had an extra arrow func indicator, e.g., it('does things', () => () => {Banjo
If for whatever reason checking manually, where "fail(...);" is used, calling "expect().nothing();" is supported nowadays (to silence warning).Funky
P
28

In general, when testing the async callback functions, it is always important to expect the outputs of the test after the promises are resolved. You can use the Angular test bed framework's tick() with the fakeAsync() or you can simply fallback to the Jasmine's general way of testing the async methods by using done()

Using done():

it('my spec', (done) => {
  array = [];
  service.output.subscribe(e => {
   array.push(e);
   for(let i = 0; i< array.length - 1; i++) {
    expect(array[i].f).toBeLessThan(array[i+1].f);
   }
   done();
  });
});

Hope this answer helps.

Note: I didn't had great luck with the fakeAsync() and tick(), so I am not including it in the answer. Sorry about that.

Pragmatic answered 21/8, 2017 at 17:2 Comment(0)
C
20

Try using async function from @angular/core/testing. It

Wraps a test function in an asynchronous test zone. The test will automatically complete when all asynchronous calls within this zone are done. Can be used to wrap an {@link inject} call.

Please find code example below:

it('...', async(inject([AClass], (object) => {
  object.doSomething.then(() => {
   expect(...);
  })
});
Ceceliacecil answered 25/5, 2018 at 17:15 Comment(0)
S
5

I was successful in using waitForAsync to wrap my it function in.

it('should display correct data', waitForAsync(() => {

    fixture.whenStable().then(() => {
      // expect 
    });
 }));
Superheterodyne answered 11/6, 2021 at 12:24 Comment(0)
G
2

You should use done() at the end of the promise, but from Jasmine 2.8.0 that will not work because there is not implementation for a done() method. You should test your promises like:

it('does test promise',
    inject([MyService], async (myService: MyService) => {
        const result = await myService.serviceToTest()
        expect(result).not.toBeNull()
        expect(result).toBe('Some Value')
     })
)

Hope that this help you

Gravois answered 23/10, 2019 at 16:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.