繁体   English   中英

测试 i18next 抱怨“无法读取未定义的属性‘使用’”

[英]Testing i18next complain about "Cannot read property 'use' of undefined"

我用过笑话

    jest.mock('i18next', () => ({
        use: () => this,
        init: () => { },
        t: k => k
      }));

没有解决问题。 我收到TypeError: Cannot read property 'use' of undefined

但是如果我使用 require 模块而不是 import for i18next 就可以了

const i18next = require('i18next'); // works
import i18next from 'i18next'; // will fail jest test with TypeError: Cannot read property 'use' of undefined

并试图用谷歌搜索解决方案,但找不到适合我的解决方案。

import i18next from 'i18next'
import languageDetector from "i18next-browser-languagedetector";
import { languageData } from './language.resources';

export class Translation {
  private static _instance: Translation;
  isInitialized : boolean = false;  
  private resources = languageData;
  private detectOptions = {
    order: ['navigator', 'localStorage', 'sessionStorage', 'cookie', 'htmlTag', 'path', 'subdomain'],
    lookupLocalStorage: 'lng'
  }

  constructor() {
  }

  setLanguageResources(data) {
     this.resources = data;     
  } 

  initi18n() {
    i18next
    .use(languageDetector)
    .init({
      resources: this.resources,
      fallbackLng: 'en-US',
      detection: this.detectOptions,
      debug: true,
      returnEmptyString: false,
      ns: [
        'translation',
        'validation',
        'error'          
      ],
    });
    this.isInitialized = true;
  }

  get i18nInstance() {  
      return i18next;
  }

  translate(key : string) {
    return i18next.t(key);
  }

  static getInstance() {
    if(this._instance) {
      return this._instance;
    }

    this._instance = new Translation();
    this._instance.initi18n();
    return this._instance;
  }
}

测试规范文件

import * as i18next from 'i18next';
import { Translation } from './translation.utility';

describe('Translation', () => {      

    jest.mock('i18next', () => ({
        use: () => this,
        init: () => { },
        t: k => k
      }));


    it('should create an instance', () => {
      expect(new Translation()).toBeTruthy();
    });

    it('should test setResource', () => {
        let translate = new Translation();
        translate.setLanguageResources({});
        expect(translate["resources"]).toEqual({})        
    });

    it('should test new Translation singleton object', () => {
        let translate = new Translation();
        translate.setLanguageResources({});
        expect(translate["resources"]).toEqual({})    
        
        translate = Translation.getInstance();
        expect(translate.isInitialized).toEqual(true);
    });

    it('should test singleton', () => {
        let translate = Translation.getInstance();
        translate.setLanguageResources({});
        expect(translate.isInitialized).toEqual(false);
        expect(translate["resources"]).toEqual({})        
    });

    xit('should test init i18next', () => {
        let translate = new Translation();
        translate.i18nInstance;
        expect(translate.translate("")).toBeDefined();        
    });
})

jest.config.js 文件

module.exports = {
  name: "translation",
  preset: "../../jest.config.js",
  setupFilesAfterEnv: ["<rootDir>/src/test-setup.ts"],
  globals: {
    "ts-jest": {
      tsConfig: "<rootDir>/tsconfig.spec.json",
      stringifyContentPathRegex: "\\.(html|svg)$",
      astTransformers: [
        "jest-preset-angular/build/InlineFilesTransformer",
        "jest-preset-angular/build/StripStylesTransformer",
      ],
    },
  },
  coverageDirectory: "../../coverage/libs/translation",
  snapshotSerializers: [
    "jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js",
    "jest-preset-angular/build/AngularSnapshotSerializer.js",
    "jest-preset-angular/build/HTMLCommentSerializer.js",
  ],
};

tsconfig.lib.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "../../dist/out-tsc",
    "target": "es2015",
    "declaration": true,
    "declarationMap": true,
    "inlineSources": true,
    "module": "commonjs",
    "types": [],
    "lib": ["dom", "es2018"]
  },
  "angularCompilerOptions": {
    "skipTemplateCodegen": true,
    "strictMetadataEmit": true,
    "enableResourceInlining": true
  },
  "exclude": ["src/test-setup.ts", "**/*.spec.ts"],
  "include": ["**/*.ts"]
}

这可能是因为 tsconfig.xml 中的"module": "commonjs"

在这里您可以看到不同模块类型的含义: tsconfig.json 中的模块类型之间的区别

我可以通过更改我模拟i18n的方式来解决类似的问题。

这是我使用的:

jest.mock('../../src/i18n', () => ({
    __esModule: true,
    use: () => {},
    init: () => {},
    default: {
        t: (k) => k,
    },
}));

在我的例子中,我在我的src/i18n.ts文件中导入i18next ,所以这就是我用那个字符串模拟它的原因。 您也许可以使用i18next而不是'../../src/i18n'

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM