jest.mock中的Jest'TypeError:is not a function'

时间:2018-08-21 23:00:04

标签: javascript unit-testing mocking jestjs

我正在编写一个Jest模拟,但是在模拟本身之外定义模拟函数时似乎有问题。

我有一堂课

myClass.js    

class MyClass {
  constructor(name) {
    this.name = name;
  }

  methodOne(val) {
    return val + 1;
 }

  methodTwo() {
    return 2;
  }
}

export default MyClass;

以及使用它的文件:

testSubject.js

import MyClass from './myClass';

const classInstance = new MyClass('Fido');

const testSubject = () => classInstance.methodOne(1) + classInstance.name;

export default testSubject;

和测试:     testSubject.test.js

import testSubject from './testSubject';

const mockFunction = jest.fn(() => 2)

jest.mock('./myClass', () => () => ({
    name: 'Name',
    methodOne: mockFunction,
    methodTwo: jest.fn(),
}))


describe('MyClass tests', () => {
    it('test one', () => {
        const result = testSubject()

        expect(result).toEqual('2Name')
    })
})

但是,出现以下错误:

TypeError: classInstance.methodOne is not a function

如果我改写:

...
methodOne: jest.fn(() => 2)

然后测试顺利通过。

是否可以在模拟本身之外定义此方法?

谢谢!

9 个答案:

答案 0 :(得分:1)

我知道了。这与起吊有关,请参阅:Jest mocking reference error

它在我以前做过的测试中起作用的原因是因为我是testSubject本身就是一个类。这意味着在实例化testSubject时,它位于测试文件中的变量声明之后,因此该模拟程序有权使用它。

因此,在上述情况下,它永远无法正常工作。

答案 1 :(得分:0)

就我而言,我不得不模拟一个节点模块。我在ES6中使用React和Redux,并在Jest和Enzyme中进行单元测试。

在我正在使用并为其编写测试的文件中,我默认将节点模块导入:

import nodeModulePackate from 'nodeModulePackage';

因此,由于一直出现错误(0, _blah.default) is not a function.,因此我需要将其作为默认值进行模拟。 我的解决方法是:

jest.mock('nodeModulePackage', () => jest.fn(() => {}));

就我而言,我只需要重写该函数并使它返回一个空对象。

如果需要在该节点模块上调用函数,请执行以下操作:

jest.mock('nodeModulePackage', () => ({ doSomething: jest.fn(() => return 'foo') }));

希望这对某人有所帮助:)

答案 2 :(得分:0)

就我而言,它来自module.exports

代替写作

module.exports = {sum: sum};

module.exports = sum;

注意:sum是一个将两个数字相加的函数

答案 3 :(得分:0)

万一任何人仍然面临着类似的问题,要解决失败的测试,我必须返回一个模拟函数,如下所示:

const tea = TeamMaker.makeTea();
tea(); // TypeError: tea is not a function


jest.mock('url/to/TeamMaker', () => ({ makeTea: jest.fn(() => jest.fn) })); // tests passed

答案 4 :(得分:0)

mockOne 定义为未赋值的 let,然后在模拟函数中初始化变量对我有用:

let mockFunction

jest.mock('./myClass', () => () => {
    mockFunction = jest.fn(() => 2)
    return {
        name: 'Name',
        methodOne: mockFunction,
        methodTwo: jest.fn(),
    }
}))

答案 5 :(得分:0)

就我而言,它是导入,如 Getting `TypeError: jest.fn is not a function` 中所述(张贴在这里是因为我的问题在 from keep_alive import keep_alive import discord import os import requests import json import random from discord import FFmpegPCMAudio from discord.ext.commands import Bot client = discord.Client() sad_words = ["sad", "depressed", "unhappy", "angry", "miserable", "sorrowful", "regretful", "downcast", "miserable", "downhearted", "despondent", "despairing", "disconsolate" ] starter_encouragements = [ "Cheer up! Turn that frown upside down!", "Hang in there. It will all soon pass.", "You are a great person!(Hopefully :-P)", "Use your sharp-sightedness to make clear distinctions and wise choices. Move forward with confidence in your inner compass.", "Give yourself another day, another chance. You will find your courage eventually. Don't give up on yourself just yet.", "Don't let life discourage you; everyone who got where he is had to begin where he was.", "Even if you're on the right track, you'll get run over if you just sit there.", "There are two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle." ] def get_quote(): response = requests.get("https://zenquotes.io/api/random") json_data = json.loads(response.text) quote = json_data[0]['q'] + " -" + json_data[0]['a'] return(quote) client = Bot(command_prefix=list('PREFIX')) @client.event async def on_ready(): print('We have logged in as {0.user}'.format(client)) @client.event async def on_message(message): if message.author == client.user: return msg = message.content if message.content.startswith('#hello'): await message.channel.send('Hello! Hope you are having a nice day, bud!') if message.content.startswith('#inspire'): quote = get_quote() await message.channel.send(quote) if any(word in msg for word in sad_words): await message.channel.send(random.choice(starter_encouragements)) @client.command(aliases=['p']) async def play(ctx, url: str = 'http://stream.radioparadise.com/rock-128'): channel = ctx.message.author.voice.channel global player try: player = await channel.connect() except: pass player.play(FFmpegPCMAudio('http://stream.radioparadise.com/rock-128')) @client.command(aliases=['s']) async def stop(ctx): player.stop() keep_alive() client.run(os.getenv('TOKEN')) 中出现,所以我首先查看了此处)。

基本问题是有人投入了

jest.mock

但那是错误的(应该是玩笑而不是玩笑)。这在 Node.js 10 中与最初放置的行一起工作。它在 Node.js 14 中不起作用。我猜他们使用了不同版本的 Jest,也许是间接的(其他包需要为 14 更新)。

const jest = require('jest');

此外,在测试文件中,它可能已经为您完成,因此您不需要任何东西。没有该行,文件将正常运行。

Linting 可能会在省略该行时出现错误,但可以使用

修复此错误
const jest = require('jest-mock');

或者如果您已经使用 /* global jest */ 这样做了,

expect

当第一次使用 /* global expect, jest */ 之后或之前出现该行时,linter 看起来很高兴。如果您的 linter 工作方式相同,您可以根据可读性而不是功能要求来选择顺序。

答案 6 :(得分:0)

就我而言,问题在于我导出文件的方式。

我试图模拟的文件被导出如下: export const fn = () => {};

我写的模拟文件被导出为:

const fn = () => {};
export default fn;

一旦我确定模拟文件也像要模拟的文件一样被导出,我就没有这个问题

答案 7 :(得分:0)

以下是对我有用的答案

 import {testSubject} from '../testsubject';

 describe('sometest',(){

 it('some test scenario',()=>{
  
  testSubject.mockReturnValue(()=>jest.fn);

  })

 })

答案 8 :(得分:0)

我正在编写我的版本,以防它对某人有帮助。

我在模拟 firebase-admin 时遇到错误。 我像下面这样开玩笑地嘲笑 firebase-admin

jest.mock('firebase-admin');

但我开始收到以下错误:

firebase_admin_1.default.messaging is not a function

它即将到来是因为在应用代码中,我像这样使用了 firebase-admin

await admin.messaging().send(message) 

(消息是 TokenMessage 的一个实例)

问题是我没有嘲笑成员变量和成员方法。这里是成员方法 messagingmessaging 中名为 send 的嵌套成员方法。 (请参阅在 messaging 上调用 admin 方法,然后在 send 的值上调用 admin.messaging())。所需要做的就是像下面这样模拟这些:

jest.mock('firebase-admin', () => ({
  credential: {
    cert: jest.fn(),
  },
  initializeApp: jest.fn(),
  messaging: jest.fn().mockImplementation(() => {
    return {
      send: jest
        .fn()
        .mockReturnValue('projects/name_of_project/messages/message_id'),
    };
  }),
}));

(请注意,我还根据最初的要求模拟了其他成员变量/方法。您可能也需要这些模拟)