Your are using original window
API, you are not mocking it, so the method postMessage
will keep it's asynchronous behavior. Knowing that, tests should be written in an asynchronous way. In JSFiddle you have Jasmine 1.3, so test should look kinda like this:
it('should ....', function () {
var done = false;
spyOn(MyService,'handleMessage').andCallFake(function () {
// set the flag, let Jasmine know when callback was called
done = true;
});
runs(function () {
// trigger async call
$window.postMessage('message','*');
});
waitsFor(function () {
// Jasmine waits until done becomes true i.e. when callback be called
return done;
});
runs(function () {
expect(MyService.handleMessage).toHaveBeenCalled();
});
});
Check the docs about testing async with Jasmine 1.3. And here is a working JSFiddle.
It would be a bit easier in Jasmine 2.x:
it('should ....', function (done) {
spyOn(MyService,'handleMessage').and.callFake(function () {
expect(MyService.handleMessage).toHaveBeenCalled();
done();
});
$window.postMessage('message','*');
});
Also, I have to mention, that you have to change how you add a listener from this
angular.element($window).on('message', MyService.handleMessage);
to that
angular.element($window).on('message', function (e) {
MyService.handleMessage(e);
});
because .on
registers a function itself, it won't be used as a method attached to the MyService
, so you won't be able to spy on it.