如何在Jasmine中假装离线?

car*_*ism 2 javascript unit-testing jasmine karma-jasmine

我有一个JavaScript函数,该功能在离线时和在线时的行为可能有所不同,以作为一种保障。我想进行一次Jasmine单元测试,以在离线和在线模式下测试该功能-例如,

// 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();
  });
});
Run Code Online (Sandbox Code Playgroud)

但是,我无法伪造的价值navigator.onLine。在我的中before,我还尝试了:

navigator = {
  'onLine': false
}
Run Code Online (Sandbox Code Playgroud)

这也不起作用。彻底来说,我尝试了与上述相同的技术window.navigator.onLine,但同样没有用。

有谁知道如何模拟离线进行茉莉花测试?

try*_*lly 5

您没有机会覆盖一些内置属性。虽然,Object.defineProperty()您可以重新配置内置属性。

Jasmine 2.6及更高版本

从Jasmine 2.6(发行说明)开始spyOnProperty()

这就是您监视的方式navigator.onLine

beforeEach(function(){
    spyOnProperty(Navigator.prototype, 'onLine').and.returnValue(false);
});
Run Code Online (Sandbox Code Playgroud)

注意,原型对象Navigator是引用的,不是实例window.navigator

茉莉花2.6

为浏览器对象构建外观

使用Jasmine 2.6之前的版本,您无法直接监视属性(或属性)。

我建议使用getter方法为此类浏览器内置对象创建外观。然后,您可以在测试中模拟那些方法以返回所需的内容。

const Browser = (function() {
    return {
        isOnline: function() {
            return navigator.onLine;
        }
    };
})();
Run Code Online (Sandbox Code Playgroud)

在您的代码中:

if (Browser.isOnline()) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

在您的测试中:

beforeEach(function(){
    spyOn(Browser, 'isOnline').and.returnValue(false);
});
Run Code Online (Sandbox Code Playgroud)

spyOnProperty()你自己做

如果由于某种原因无法从2.6之前的版本升级,甚至可以利用Object.defineProperty()和进行手动监视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
    });
});
Run Code Online (Sandbox Code Playgroud)

spyOnProperty()如果您不顾一切,甚至可以实现自己的反向端口(尽管这超出了这个答案)。