简体   繁体   English

Jest - 在打字稿中模拟一个命名的类导出

[英]Jest - mock a named class-export in typescript

I have a node module which exports a few classes, one of which is Client , which I use to create a client (having a few APIs as methods).我有一个节点模块,它导出了一些类,其中一个是Client ,我用它来创建一个客户端(有一些 API 作为方法)。

I'm trying to test my module which uses this node module as a dependency using Jest.我正在尝试使用 Jest 测试我的模块,该模块将此节点模块用作依赖项。 However, I've been unable to successfully mock the one method (say search() ) in the Client class.但是,我无法成功模拟 Client 类中的一种方法(比如search() )。

Here is my spec for myModule :这是我的myModule规范:

 //index.spec.ts import * as nock from 'nock'; import * as externalModule from 'node-module-name'; import { createClient } from './../../src/myModule'; describe(() => { beforeAll(() => { nock.disableNetConnect(); }); it('test search method in my module', () => { jest.mock('node-module-name'); const mockedClient = <jest.Mock<externalModule.Client>>externalModule.Client; const myClient = createClient({/*params*/}); //returns instance of Client class present in node module by executing Client() constructor myClient.searchByName('abc'); //calls search API - I need to track calls to this API expect(mockedClient).toHaveBeenCalled(); expect(mockedClient.prototype.search).toHaveBeenCalledWith('abc'); }); });

This, however, doesn't create a mock at all and triggers a nock error since the search API tries to connect to the url (given through params).但是,这根本不会创建模拟并触发 nock 错误,因为搜索 API 会尝试连接到 url(通过参数给出)。

I've also tried mocking the Client class like the following.我也尝试过像下面这样模拟 Client 类。 While successfully creating a mock for the Client class and also the search API (verified that search() is also mocked through console logs), it gives me an error while I try to check if search() has been called.虽然成功地为 Client 类和搜索 API 创建了一个模拟(验证search()也通过控制台日志模拟),但当我尝试检查search()是否已被调用时,它给了我一个错误。

 externalModule.Client = jest.fn(() => { return { search: jest.fn(() => Promise.resolve('some response')) } }); //creates the mock successfully, but not sure how to track calls to 'search' property const client = myModule.createClient(/*params*/); client.searchByName('abc'); expect(externalModule.Client).toHaveBeenCalled(); //Successful expect(externalModule.Client.prototype.search).toHaveBeenCalled(); //returns error saying "jest.fn() value must be a mock function or spy, Received: undefined"

I'm not sure what I'm doing wrong.我不确定我做错了什么。 Thank you in advance.先感谢您。

Mocking whole module模拟整个模块

Try moving jest.mock to the top of file尝试将jest.mock移动到文件顶部

//index.spec.ts
const search = jest.fn();
jest.mock('node-module-name', () => ({
  Client: jest.fn(() => ({ search }))
}));
import * as nock from 'nock';
import * as externalModule from 'node-module-name';
import { createClient } from './../../src/myModule';
describe(() => {
  beforeAll(() => {
    nock.disableNetConnect();
  });
  it('test search method in my module', () => {
    const myClient = createClient({/*params*/});
    myClient.searchByName('abc'); 

    expect(externalModule.Client).toHaveBeenCalled();
    expect(search).toHaveBeenCalledWith('abc');
    externalModule.Client.mockClear();
    search.mockClear();
  });
});

Mocking only Client仅模拟客户端

Create search constant and track it.创建search常量并跟踪它。

const search = jest.fn();
externalModule.Client = jest.fn(() => ({ search }));

const client = myModule.createClient(/*params*/);
client.searchByName('abc');

expect(externalModule.Client).toHaveBeenCalled();
expect(search).toHaveBeenCalled();

Here is how I mocked it.这就是我嘲笑它的方式。 I had to change naming and removing some code to avoid exposing original source.我不得不更改命名并删除一些代码以避免暴露原始源代码。

jest.mock('../foo-client', () => {
  return { FooClient: () => ({ post: mockPost }) }
})

Full code.完整的代码。

// foo-client.ts

export class FooClient {
    constructor(private config: any)
    post() {}
}

// foo-service.ts

import { FooClient } from './foo-client'

export class FooLabelService {
    private client: FooClient
    constructor() {
        this.client = new FooClient()
    }

    createPost() {
        return this.client.post()
    }
}

// foo-service-test.ts

import { FooService } from '../foo-service'

const mockPost = jest.fn()
jest.mock('../foo-client', () => {
  return { FooClient: () => ({ post: mockPost }) }
})

describe('FooService', () => {
  let fooService: FooService

  beforeEach(() => {
    jest.resetAllMocks()
    fooService = new FooService()
  })

  it('something should happened', () => {
    mockPost.mockResolvedValue()
    fooService.createPost()
  })
})

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

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