簡體   English   中英

如何更改Jasmine包含的Javascript文件中定義的全局變量?

[英]How to change a global variable defined in an included Javascript file from Jasmine?

背景

我花了最后幾個小時來嘗試找到答案,但這可能是由於我對require.js缺乏了解。

我正在使用的是:我有一個緊密耦合的遺留企業Web應用程序,該應用程序編寫於2001年,當時使用的是IE 5特定的Javascript。 名為Menu.js的Javascript文件具有使HTML表能夠像菜單一樣工作的功能,其中表單元格是菜單項,其中一些菜單項可以擴展子菜單,即更多的表單元格。

簡而言之,代碼是錯誤的。 但是,我必須提供一個創可貼以使其與Chrome和Firefox兼容。 解決方案是重寫每個Javascript函數的內部結構以使用jQuery,以便它與跨瀏覽器兼容。

每個網頁都包含Menu.js ,並且每個網頁都是自動生成的,因此我被迫通過從Menu.js注入jQuery來包含jQuery,該代碼具有以下代碼:

Menu.js

function injectQuery() {
  const script = document.createElement('script');
  script.src = 'https://code.jquery.com/jquery-3.2.1.min.js';
  document.getElementByTagName('head')[0].appendChild(script);
}

injectJQuery();

function getSubMenu(el) {
  return $(el).find('table')[0] || null;
}

// Other functions are defined here as well

if ( typeof module !=== 'undefined' && module.hasOwnProperty('exports') ) {
  module.exports.getSubMenu = getSubMenu;
}

在Jasmine中,當測試Menu.js ,如果沒有得到未定義的錯誤,我將無法使用$()函數。 為了解決這個問題,我有以下代碼:

menu.spec.js

const sut = require('../src/js/Menu.js');
const testMenu = require('./resources/test.menu').data();

const { JSDOM } = require('jsdom');
const { window } = new JSDOM();
const { document } = window.window;
const jQuery = require('jquery')(window);

global.$ = jQuery;

describe('getSubMenu()', () => {
  beforeEach(() => {
    document.querySelector('body').innerHTML = testMenu;
  });

  it('should return the nested sub-menu-3 table given the sub-menu-2 element', () => {
    const subMenu2 = $('#sub-menu-2');
    const result = sut.getSubMenu(subMenu2);

    expect(result.id).toBe('sub-menu-3');
  });
});

問題

每當運行規范時,都會出現以下錯誤:

const script = document.createElement('script');
                        ^
ReferenceError: document is not defined
    at injectJquery

因此,我不希望在Jasmine規范運行時運行Menu.js定義的injectJquery()方法。 我嘗試了以下方法:

嘗試1-從Jasmine更改全局值

Menu.js

var isUnderTest = false;

...

if (!isUnderTest) {
  injectJquery();
}

...

if ( typeof module !=== 'undefined' && module.hasOwnProperty('exports') ) {
  ...
  module.exports.isUnderTest = isUnderTest;
}

menu.spec.js ,我嘗試設置以下內容:

sut.isUnderTest = true;

但是,規范仍然嘗試執行injectJquery()並且我收到了相同的錯誤。 我嘗試為isUnderTest變量定義一個setter函數並調用它,然后導出該函數,但是我仍然收到相同的錯誤。

嘗試2-使用茉莉花間諜強制該功能不執行任何操作

我嘗試使用Jasmine間諜程序通過以下代碼使函數不執行任何操作:

spyOn(sut, 'injectJquery').and.callFake(() => null);

我還做了導出injectJquery()從內部功能Menu.js ; 但是,那也不起作用。

嘗試3-定義節點全局變量

我試圖在menu.spec.js定義節點全局變量, menu.spec.js所示:

global.isUnderTest = true;

但是,它仍然不起作用。

最后的想法

來自Java世界並使用JUnit,盡管我知道Javascript文件Menu.js不是對象,但我希望我在Jasmine中定義的測試對象系統的行為類似於Java。

我希望injectJquery()在瀏覽器中運行,但不在規范中運行。 有什么方法可以抑制我沒有看到的方法調用?

經過長時間的反復試驗,我決定通過以下方法使用破解的方法來解決此問題:

try {
  injectJquery();
} catch (e) {
  if (e instanceof ReferenceError) {
    // The system is under test: do nothing
  }
}

希望這可以幫助使用Jasmine測試舊版Javascript的其他人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM