首页 > 解决方案 > 使用静态成员时如何避免 Jasmine 测试中的竞争条件?

问题描述

我有使用 Karma 运行的 Jasmine 测试。这些测试涵盖具有用于控制行为的静态属性的对象。更改这些静态属性会对不希望它们偏离默认值的测试产生不利影响。更具体地说,这个测试:

it('honors the base64CharactersPerLine option', () => {
    const testData = new Uint8Array([ 0x01, 0x02, 0x03, 0x04 ]);
    const pem = new PEMObject();
    pem.header = "CERTIFICATE";
    pem.data = testData;
    PEMObject.base64CharactersPerLine = 1; // Causes race condition
    const encodedData = pem.encode();
    console.info(encodedData);
    console.info(encodedData.match(/^\w/g));
    expect(encodedData.match(/^\w$/g).length).toBeGreaterThan(testData.length);
});

正在对该测试产生不利影响:

it('decoding then encoding returns the original data', () => {
    const pem = new PEMObject();
    pem.header = "CERTIFICATE";
    pem.decode(testPEM);
    expect(pem.encode()).toEqual(testPEM);
});

通过使pem.encode()后一个测试中的输出与原始输入testPEM(a string) 不同。

我想知道的更普遍的问题是:在使用静态成员修改行为的 Karma/Jasmine 测试中,您如何防止竞争条件?

标签: javascripttypescriptjasminekarma-jasminekarma-runner

解决方案


在测试中为静态值分配新值将影响以后运行的所有其他测试。

有两种方法可以解决此问题。首先,在一个beforeEach块中,缓存静态属性的原始值,然后在一个afterEach块中将其重置。像这样:

let cachedValue;
beforeEach(() => cachedValue = PEMObject.base64CharactersPerLine);
afterEach(() => PEMObject.base64CharactersPerLine = cachedValue);

这将起作用,但如果您在测试期间有很多要操作的静态属性,维护和推理会很复杂。

更好的方法是从使用静态属性改为使用静态方法(尽管这需要更改您的基本代码)。使用静态方法后,您就可以使用 jasmine 间谍,每次测试运行后都会对其进行清理。所以,你会做这样的事情:

// in your base code
PEMObject.getBase64CharactersPerLine = () => SOME_VALUE;

// in your 'honors the base64CharactersPerLine option' test
spyOn(PEMObject, 'getBase64CharactersPerLine').and.returnValue(1);

你不再需要beforeEach/afterEach块。


推荐阅读