【问题标题】:Jest Unit Test Singleton class NodejsJest 单元测试 Singleton 类 Nodejs
【发布时间】:2021-05-01 18:36:59
【问题描述】:

我在下面的代码中尝试对使用单例类的类变量的函数进行单元测试

单例类 a.js

class A{
constructor(){
   this.flag = true;
 }
 
setA(){
  this.flag=false;
  }
}

module.exports = new A(); //Singleton

使用单例类的类

import A from './a';

class B {
  constructor() {}

  hello() {
    if (A.flag) {
      console.log('1');
    } else {
      console.log('2');
    }
  }
}

b.test.js 的单元测试用例

import A from './a' //Singleton class
import B from './'

describe('Test Hello', () => {
    const b= new B();
    
    beforeEach(() => {      
    });

    afterEach(() => {
        jest.restoreAllMocks();
    })


    test('Test Hello', async () => {        
        try{
            jest.spyOn(A, 'flag')
                .mockResolvedValueOnce(true);
            let output = b.hello();
                    
        }catch(e){
            console.log('Error', e);
        }
    });
});

所以 b.js 中的一行,console.log(1) 没有被覆盖在覆盖率报告中。尝试了多种选择

【问题讨论】:

    标签: node.js unit-testing jestjs mocking singleton


    【解决方案1】:

    你的代码有很多问题:

    1. 您正在测试b.js 模块,而不是a.js 模块。所以测试文件名应该是b.test.js

    2. 导入的模块名称错误。应该是./a.js,而不是A.js

    3. 如果要改变实例a的属性,只需要在测试用例中赋值即可

    例如

    a.js:

    class A {
      constructor() {
        this.flag = true;
      }
    
      setA() {
        this.flag = false;
      }
    }
    
    module.exports = new A(); //Singleton
    

    b.js:

    import a from './a';
    
    export class B {
      constructor() {}
    
      hello() {
        if (a.flag) {
          console.log('1');
        } else {
          console.log('2');
        }
      }
    }
    

    b.test.js:

    import a from './a';
    import { B } from './b';
    
    describe('67335501', () => {
      afterEach(() => {
        jest.restoreAllMocks();
      });
    
      it('should print "1"', () => {
        const logSpy = jest.spyOn(console, 'log');
        a.flag = true;
        const b = new B();
        b.hello();
        expect(logSpy).toBeCalledWith('1');
      });
    
      it('should print "2"', () => {
        const logSpy = jest.spyOn(console, 'log');
        a.flag = false;
        const b = new B();
        b.hello();
        expect(logSpy).toBeCalledWith('2');
      });
    });
    

    单元测试结果:

     PASS  examples/67335501/b.test.js (10.808 s)
      67335501
        ✓ should print "1" (18 ms)
        ✓ should print "2" (2 ms)
    
      console.log
        1
    
          at console.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
    
      console.log
        2
    
          at console.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |    87.5 |      100 |      75 |    87.5 |                   
     a.js     |   66.67 |      100 |      50 |   66.67 | 7                 
     b.js     |     100 |      100 |     100 |     100 |                   
    ----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       2 passed, 2 total
    Snapshots:   0 total
    Time:        12.657 s
    

    【讨论】:

    • 我在单例类中添加了一个随机字符串__debugRandomId = Math.random().toString(36).substring(2, 15);,在b.test.js 中显示相同。但是,在另一个测试文件a.test.js 中,这两个__debugRandomId 在两个测试中是不同的,这意味着它们不是同一个实例。有什么方法可以使它们相同吗?
    猜你喜欢
    • 2019-08-23
    • 2020-03-30
    • 2018-03-11
    • 2012-02-29
    • 2018-12-16
    • 2020-08-04
    • 2018-12-24
    • 2022-01-06
    • 2022-01-02
    相关资源
    最近更新 更多