Макет импортированного класса в машинописном тексте с помощью jest

Я пытаюсь использовать шутку для имитации импортированного класса внутри класса машинописного текста, следующий код используется для основной программы (я удалил некоторый код изнутри функций, но все еще должно быть ясно, что я пытаюсь сделать)

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.info(loginCreds.username, loginCreds.password, client.id);
                    this._authenticationService.authenticateUser(loginCreds.username, loginCreds.password, client.id);
                });
            }
        );
    }
}

Я пытаюсь имитировать функцию «authenticateUser» в «AuthenticationService», вместо того, чтобы вызывать обычный код, я хочу имитировать обещание. Я пробовал использовать примеры, приведенные в 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: свойство mock не существует для типа typeof AuthenticationService.

Что я здесь делаю не так? Должен ли я по-другому издеваться над классом / функцией, поскольку он использует обещания?

эта ошибка является ошибкой ввода TypeScript. вы можете поделиться своим тестовым кодом?

Brian Adams 27.11.2018 19:26

Привет, Брайан, я добавил небольшой фрагмент тестового кода, но проблема в том, что я не могу запустить тест, потому что не могу издеваться над классом.

devran 28.11.2018 08:17
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
6
2
17 801
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема

Типизация для AuthenticationService не включает свойство mock, поэтому TypeScript выдает ошибку.


Подробности

jest.mock создает автоматический макет модуля, который «заменяет класс ES6 фиктивным конструктором и заменяет все его методы фиктивными функциями, которые всегда возвращают undefined».

В этом случае экспорт default из authentication.service.ts является классом ES6, поэтому он заменяется имитирующим конструктором.

У макетного конструктора есть свойство 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];

Спасибо за вашу помощь, используя ваш код, я понял, как имитировать функцию в классе, спасибо, что вы также включили детали, теперь это делает его более понятным.

devran 29.11.2018 09:00

@ brian-live-outdoors Я пробовал это, но по какой-то причине машинописный текст все еще смотрит на экземпляр Mocked как на реальный тип, над которым он насмехается ... есть идеи? (пытается издеваться над интерфейсом)

Mithir 17.04.2019 10:09

На самом деле это не работает для меня, потому что TypeScript говорит мне, что мне нужно сначала преобразовать его в unknown. т.е. original as unknown as jest.Mocked<typeof original> Кто-нибудь знает способ обойти это?

Chris Watts 21.05.2019 20:16

У меня это не работает. AuthenticationService.mockClear (); производит -> свойство mockClear не существует в bla bla. Осматривая объект у него есть mockClear, mock и т. д. Но типы машинописного текста не известны.

rsan 22.05.2019 06:59

Пришлось заменить const AuthenticationService = mocked.default; на const AuthenticationService = mocked.AuthenticationService, у меня это сработало. Я использую ts-jest 25.2.1.

Stefan Frye 03.03.2020 08:26

TS2339: Свойство «default» не существует для типа «Mocked».

Alexey Sh. 09.08.2021 23:44

Другие вопросы по теме