How to fake being offline in Jasmine?

守給你的承諾、 提交于 2019-12-07 21:47:09

问题


I have a javascript function which is supposed to behave differently when offline than online as a safeguard. I would like to have a Jasmine unit test which tests the function in both offline and online modes - e.g.,

// offline
describe('When there is no connection to the internet', function() {
  beforeEach(function(){
    spyOn(navigator, 'onLine').and.returnValue(false);
  });

  it('offline behavior happens', function() {
    myFunction();

    expect(something).not.toHaveBeenCalled();
  });
});

// online
describe('When there is a connection to the internet', function() {
  beforeEach(function(){
    spyOn(navigator, 'onLine').and.returnValue(true);
  });

  it('online behavior happens', function() {
    myFunction();

    expect(something).toHaveBeenCalled();
  });
});

However, I am unable to fake the value of navigator.onLine. In my before, I also tried:

navigator = {
  'onLine': false
}

This didn't work either. To be thorough, I tried the same techniques above with window.navigator.onLine and that also didn't work.

Does anyone know how to mock being offline for a Jasmine test?


回答1:


You have no chance to overwrite some built in properties. Though with Object.defineProperty() you can reconfigure builtin properties.

Jasmine 2.6 and newer

Since Jasmine 2.6 (release notes) there is spyOnProperty().

This is how you would spy navigator.onLine:

beforeEach(function(){
    spyOnProperty(Navigator.prototype, 'onLine').and.returnValue(false);
});

Note that the prototype object Navigator is referenced, not it's instance window.navigator.

Jasmine pre 2.6

Build a facade for browser objects

With pre Jasmine 2.6 you can't spy attributes (or properties) directly.

I'd suggest to create a facade for such browser builtins using getter methods. Then you can mock those methods in your tests to return what you like.

const Browser = (function() {
    return {
        isOnline: function() {
            return navigator.onLine;
        }
    };
})();

In your code:

if (Browser.isOnline()) {
    // ...
}

In your test:

beforeEach(function(){
    spyOn(Browser, 'isOnline').and.returnValue(false);
});

Do what spyOnProperty() does on your own

If you cannot upgrade from a pre 2.6 version for some reason, you could even spy manually by utilizing Object.defineProperty() and Object.getOwnPropertyDescriptor().

var onlineState,
    origOnLineProp;

beforeEach(function() {
    // Remember original config
    origOnLineProp = Object.getOwnPropertyDescriptor(Navigator.prototype, "onLine");

    onlineState = true;

    // New behavior
    Object.defineProperty(Navigator.prototype, "onLine", {
        enumerable: origOnLineProp.enumerable,
        configurable: origOnLineProp.configurable,
        get: function() { return  onlineState }
    });
});

it("...", function() {
    onlineState = false;
    expect("code").toBe("correctly functioning in offline mode");
});

afterEach(function() {
    // Restore original behavior
    Object.defineProperty(Navigator.prototype, "onLine", {
        enumerable: origOnLineProp.enumerable,
        configurable: origOnLineProp.configurable,
        get: origOnLineProp.get
    });
});

You could even implement your own spyOnProperty() backport if you're desperate (that's beyond this answer though).



来源:https://stackoverflow.com/questions/41150475/how-to-fake-being-offline-in-jasmine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!