typescript - 用 Jest 在 typescript 中模拟导入的类

标签 typescript unit-testing testing jestjs

我正在尝试使用 jest 来模拟 typescript 类中的导入类,以下代码用于主程序(我从函数内部删除了一些代码,但它仍然应该清楚我正在尝试做什么)

import * as SocketIO from "socket.io";

import {AuthenticatedDao} from "../../dao/authenticated.dao";

export default class AuthenticationService {
    private readonly _authenticatedDao: AuthenticatedDao = AuthenticatedDao.Instance;
    private readonly _io;

    constructor(socketIo: SocketIO.Server) {
        this._io = socketIo;
    }

    public authenticateUser(username: string, password: string, clientSocketId: string): void {
        this._authenticatedDao.authenticateUser(username, password).then((authenticatedUser) => {

        }).catch(rejected => {

        });
    }
}


import {createServer, Server} from 'http';
import * as express from 'express';
import * as socketIo from 'socket.io';
import {LogincredentialsDto} from "./models/dto/logincredentials.dto";
import {config} from './config/config';
import AuthenticationService from "./services/implementation/authentication.service";
import {Logger} from "./helperclasses/logger";
import {format} from "util";

export class ClassA {
    private readonly _configPort = config.socketServerPort;

    private readonly _logger: Logger = Logger.Instance;
    private _app: express.Application;
    private _server: Server;
    private _io: socketIo.Server;
    private _socketServerPort: string | number;
    private _authenticationService: AuthenticationService;


    constructor() {
        this.configure();
        this.socketListener();
    }

    private configure(): void {
        this._app = express();

        //this._server = createServer(config.sslCredentials, this._app);
        this._server = createServer(this._app);

        this._socketServerPort = process.env.PORT || this._configPort;
        this._io = socketIo(this._server);

        this._server.listen(this._socketServerPort, () => {
            this._logger.log(format('Server is running on port: %s', this._socketServerPort));
        });

        this._authenticationService = new AuthenticationService(this._io);
    }


    private socketListener(): void {
        this._io.on('connection', (client) => {
                client.on('authenticate', (loginCreds: LogincredentialsDto) => {
                    console.log(loginCreds.username, loginCreds.password, client.id);
                    this._authenticationService.authenticateUser(loginCreds.username, loginCreds.password, client.id);
                });
            }
        );
    }
}

我正在尝试模拟“AuthenticationService”中的函数“authenticateUser”,而不是调用我想模拟 promise 的普通代码。我尝试使用 https://jestjs.io/docs/en/es6-class-mocks 中提供的示例但是当我尝试执行以下操作时:

import AuthenticationService from '../src/services/implementation/authentication.service';
jest.mock('./services/implementation/authentication.service');

beforeEach(() => {
    AuthenticationService.mockClear();
});

it('test', () => {

    // mock.instances is available with automatic mocks:
    const authServerInstance = AuthenticationService.mock.instances[0];

我得到这个错误: 错误:(62, 31) TS2339:类型“typeof AuthenticationService”上不存在属性“mock”。

我在这里做错了什么?我是否应该以不同的方式模拟类/函数,因为它使用的是 promise ?

最佳答案

问题

AuthenticationService 的类型不包括 mock 属性,因此 TypeScript 会抛出错误。


详情

jest.mock 创建一个 automatic mock该模块“用模拟构造函数替换 ES6 类,并用始终返回 undefined 的模拟函数替换其所有方法”。

在这种情况下,authentication.service.tsdefault 导出是一个 ES6 类,因此它被替换为模拟构造函数。

mock 构造函数有一个 mock 属性,但 TypeScript 不知道它并且仍然将 AuthenticationService 视为原始类型。


解决方案

使用 jest.Mocked 让 TypeScript 知道 jest.mock 引起的类型变化:

import * as original from './services/implementation/authentication.service';  // import module
jest.mock('./services/implementation/authentication.service');

const mocked = original as jest.Mocked<typeof original>;  // Let TypeScript know mocked is an auto-mock of the module
const AuthenticationService = mocked.default;  // AuthenticationService has correct TypeScript typing

beforeEach(() => {
  AuthenticationService.mockClear();
});

it('test', () => {

    // mock.instances is available with automatic mocks:
    const authServerInstance = AuthenticationService.mock.instances[0];

关于typescript - 用 Jest 在 typescript 中模拟导入的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53502054/

相关文章:

java - 如何模拟/ stub jOOQ UpdatableRecordImpl store() 方法?

angularjs - 如何使用新 session 重新启动 Protractor 实例?

java,以编程方式断开网络连接

javascript - Vue 3 和 Typescript - 无法访问方法中的数据属性

通用 "promisify"函数中的 Typescript 类型推断

java - Mockito.mock(SomeClass) 和 @Mock 注释有什么区别?

unit-testing - 在 Rust 中进行单元测试后清理的好方法是什么?

python - Django & twill - 未设置 session cookie

javascript - angular 2输出后如何监听事件?

javascript - 将对象属性解构为数组值