【问题标题】:Mocking @pnp/logging in Jest在 Jest 中模拟 @pnp/logging
【发布时间】:2022-02-14 01:20:54
【问题描述】:

我正在从事一个 Spfx 项目。
我有自己的 Logger 类,它是 @pnp/logging/Logger 的包装器。

import * as pnpLogging from '@pnp/logging';
export class Logger {
    public static debug(message: string, notify = false, caller: string = null): void {
        pnpLogging.Logger.log( ... )
    }

此记录器随后用于各种其他类、组件和挂钩。

import { Logger } from "./logging";
Logger.debug('some debug message);

在为其他类之一创建测试时,jest 在导入 @pnp/logging 时会引发不受支持的异常。

通过使用他们的 commonjs 库,我能够通过 office-ui-fabric-react 克服这个问题。

"office-ui-fabric-react/lib/(.*)$": "office-ui-fabric-react/lib-commonjs/$1",

但是,我在 @pnp/logging 中看不到这个选项。
我也尝试过模拟它,但没有成功。

import { nameof } from './utils';
const mockedPnpLogger = { error: (message) => { } };
jest.mock('@pnp/logging', () => ({
  ...jest.requireActual('@pnp/logging') as any,
  Logger: mockedPnpLogger
}));   
describe('utils', () => { ... }

但这仍然会引发导出错误

SyntaxError: Unexpected token 'export'

  3 | const mockedPnpLogger = { error: (message) => { } };
  4 | jest.mock('@pnp/logging', () => ({
> 5 |     ...jest.requireActual('@pnp/logging') as any,
    |             ^
  6 |     Logger: mockedPnpLogger
  7 | }));
  8 |

我现在有点迷茫了。任何人都有一些见解或可以帮助我朝着正确的方向前进?

完整的错误信息

Jest encountered an unexpected token

Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

By default "node_modules" folder is ignored by transformers.

Here's what you can do:
 • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
 • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
 • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
 • If you need a custom transformation specify a "transform" option in your config.
 • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation

Details:

C:\Development\Projects\Skan\Applications\FuhrPark\src\client\node_modules\@pnp\logging\index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export * from "./logger.js";
                                                                                  ^^^^^^

SyntaxError: Unexpected token 'export'

> 1 | import * as pnpLogging from '@pnp/logging';

笑话配置

"jest": {
    "moduleFileExtensions": [
        "ts",
        "tsx",
        "js"
    ],
    "moduleDirectories": [
        "node_modules"
    ],
    "moduleNameMapper": {
        "\\.(css|less|scss|sass)$": "identity-obj-proxy",
        "office-ui-fabric-react/lib/(.*)$": "office-ui-fabric-react/lib-commonjs/$1",
        "^@fuhrpark/(.*)": "<rootDir>/src/webparts/fuhrpark/$1",
        "^@shared/(.*)": "<rootDir>/src/shared/$1"
    },
    "transform": {
        "^.+\\.(ts|tsx)$": "ts-jest"
    },
    "transformIgnorePatterns": [
        "node_modules/(?!office-ui-fabric-react)"
    ],
    "testMatch": [
        "**/src/**/*.tests.+(ts|tsx)"
    ],
    "setupFiles": [
        "<rootDir>/src/webparts/fuhrpark/tests/tests-setup.ts"
    ],
    "testEnvironment": "node",
    "collectCoverage": true,
    "coverageReporters": [
        "json",
        "lcov",
        "text",
        "cobertura"
    ],
    "coverageDirectory": "<rootDir>/test-results",
    "reporters": [
        "default",
        "jest-junit"
    ],
    "coverageThreshold": {
        "global": {
            "branches": 0,
            "functions": 0,
            "lines": 0,
            "statements": 0
        }
    }
},
"jest-junit": {
    "output": "./test-results/summary-jest-junit.xml"
}

TypeScript 配置

{
  "extends": "./node_modules/@microsoft/rush-stack-compiler-4.2/includes/tsconfig-web.json",
  "compilerOptions": {
    "target": "es5",
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "jsx": "react",
    "declaration": true,
    "sourceMap": true,
    "experimentalDecorators": true,
    "skipLibCheck": true,
    "outDir": "lib",
    "inlineSources": false,
    "strictNullChecks": false,
    "noUnusedLocals": false,
    "allowSyntheticDefaultImports": true,
    "resolveJsonModule": true,
    "typeRoots": [
      "./node_modules/@types",
      "./node_modules/@microsoft"
    ],
    "types": [
      "webpack-env",
      "jest",
      "node"
    ],
    "lib": [
      "es6",
      "dom",
      "es2015.collection",
      "es2015.promise"
    ],
    "baseUrl": "src",
    "paths": {
      "@fuhrpark/*": [
        "webparts/fuhrpark/*"
      ],
      "@shared/*": [
        "shared/*"
      ]
    }
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx"
  ]
}

【问题讨论】:

    标签: jestjs mocking ts-jest pnp-js


    【解决方案1】:

    我将 web 对象上的 get 方法包装在一个函数中,最后通过创建下面的模拟来正确处理它。我的包装器使用 .then 模式,这是模拟中双重承诺解决的原因。

    重要模拟不能在它/测试或描述中,它必须在顶层,如docs中所述

    我还在同一个模拟中模拟了 sp.setup 函数,否则会引发错误。因此-您需要根据我的发现设置一个双倍。我已经尝试过 ts-sinon/ts-mockito 等,但没有什么能带我一路走来。

    
    jest.mock('@pnp/sp', () => {
        return {
            __esModule: true,
            sp: {
                setup: jest.fn(),
                web: {
                    get: () => Promise.resolve(Promise.resolve({ Title: 'Contoso Web Title' }))
                }
            }
        };
    });
    

    编辑:添加一个包含“选择”的示例 - 这也必须被模拟/存根

    jest.mock('@pnp/sp', () => {
        return {
            __esModule: true,
            sp: {
                setup: jest.fn(),
                web: {
                    select: () => {
                        return {
                            get: () => Promise.resolve(Promise.resolve({ Title: 'Contoso Web Title' }))
                        };
                    }
                }
            }
        };
    });
    

    【讨论】:

    • 非常感谢 Thorild。您的示例非常有效。
    猜你喜欢
    • 2017-08-09
    • 2022-01-09
    • 2020-06-09
    • 2020-06-01
    • 2018-06-30
    • 1970-01-01
    • 2022-08-24
    • 2019-08-17
    • 1970-01-01
    相关资源
    最近更新 更多