যখন মডিউলটি আনমক করা থাকে তখন কীভাবে জেস্টে নামযুক্ত ফাংশনটিকে উপহাস করবেন


111

আমার নীচের মডিউলটি আমি জেস্টে পরীক্ষার চেষ্টা করছি:

// myModule.js

export function otherFn() {
  console.log('do something');
}

export function testFn() {
  otherFn();

  // do other things
}

উপরে প্রদর্শিত হিসাবে, এটি কিছু নামকৃত ফাংশন রফতানি করে এবং গুরুত্বপূর্ণভাবে testFnব্যবহার করে otherFn

জেস্টে যখন আমি আমার ইউনিট পরীক্ষাটি লিখছি তখন আমি ফাংশনটি testFnউপহাস otherFnকরতে চাই কারণ আমি otherFnআমার ইউনিট পরীক্ষার জন্য ত্রুটি করতে চাই না testFn। আমার সমস্যাটি হ'ল আমি নিশ্চিত যে এটি করার সর্বোত্তম উপায়:

// myModule.test.js
jest.unmock('myModule');

import { testFn, otherFn } from 'myModule';

describe('test category', () => {
  it('tests something about testFn', () => {
    // I want to mock "otherFn" here but can't reassign
    // a.k.a. can't do otherFn = jest.fn()
  });
});

কোনও সহায়তা / অন্তর্দৃষ্টি প্রশংসা করা হয়।


7
আমি এই কাজ না। বিদ্রূপ সাধারনত আপনি যেভাবেই করতে চান এমন কিছু নয়। এবং যদি আপনাকে কিছু উপহাসের প্রয়োজন হয় (সার্ভার কলগুলি করার কারণে / ইত্যাদি)) তবে আপনার কেবল otherFnএকটি পৃথক মডিউলটি বের করা উচিত এবং তা উপহাস করা উচিত।
কেন্টকড্ডস

4
আমি একই পদ্ধতির সাথে @jrubins ব্যবহার পরীক্ষা করছি testing function Aকারা ডাকে তার পরীক্ষার আচরণ function Bকিন্তু আমি এর বাস্তব বাস্তবায়ন করতে চাই না function Bকারণ আমি কেবল function A
প্রয়োগিত

44
@ কেন্টকড্ডস, "মশকরা সাধারণত যেভাবে আপনি কিছু করতে চান তা নয়" এর অর্থ আপনি কী পরিষ্কার করতে পারেন? এটি মোটামুটি বিস্তৃত (অত্যধিক প্রশস্ত?) বিবৃতি বলে মনে হয়, কারণ উপহাসটি অবশ্যই এমন কিছু যা সাধারণত ব্যবহৃত হয় (কমপক্ষে কিছু) ভাল কারণে) সুতরাং, আপনি সম্ভবত কেন উপহাস ভাল নাও হতে পারে উল্লেখ করা হয় এখানে , অথবা আপনি সত্যিই সাধারণভাবে এর অর্থ কি?
অ্যান্ড্রু উইলিয়ামস

4
প্রায়শই মশকরা প্রয়োগের বিশদ পরীক্ষা করে চলেছে। বিশেষত এই স্তরে এটি এমন পরীক্ষাগুলির দিকে পরিচালিত করে যা আপনার পরীক্ষাগুলি কাজ করে (আপনার কোডটি কাজ করে না এমনটি নয়) এর চেয়ে সত্যিকারের চেয়ে অনেক বেশি যাচাই করে না।
কেন্টকডডস

4
রেকর্ডের জন্য, বছর কয়েক আগে এই প্রশ্নটি লেখার পর থেকে আমি কতটা উপহাস করতে চাই সে সম্পর্কে আমার টিউনটি পরিবর্তন করেছি (এবং আর এটির মতো উপহাস করবেন না)। এই দিনগুলিতে আমি @ কেন্টকড্ডস এবং তার পরীক্ষার দর্শনের সাথে খুব সম্মত (এবং তাঁর ব্লগ এবং @testing-library/reactসেখানে যে কোনও রিএটারের জন্য অত্যন্ত সুপারিশ করছি) তবে আমি জানি এটি একটি বিতর্কিত বিষয়।
জন রুবিনস

উত্তর:


100

jest.requireActual()ভিতরে ব্যবহার করুনjest.mock()

jest.requireActual(moduleName)

মকটির পরিবর্তে প্রকৃত মডিউলটি ফেরত দেয়, মডিউলটি মক বাস্তবায়ন গ্রহণ করবে কিনা তা সব চেককে বাইপাস করে।

উদাহরণ

আমি এই সংক্ষিপ্ত ব্যবহারটি পছন্দ করি যেখানে আপনার প্রয়োজন হয় এবং প্রত্যাবর্তিত বস্তুর মধ্যে ছড়িয়ে পড়ে:

// myModule.test.js

jest.mock('./myModule.js', () => (
  {
    ...(jest.requireActual('./myModule.js')),
    otherFn: jest.fn()
  }
))

import { otherFn } from './myModule.js'

describe('test category', () => {
  it('tests something about otherFn', () => {
    otherFn.mockReturnValue('foo')
    expect(otherFn()).toBe('foo')
  })
})

জাস্টের ম্যানুয়াল মকস ডকুমেন্টেশনে ( উদাহরণগুলির শেষে ) এই পদ্ধতিটিও উল্লেখ করা হয়েছে :

কোনও ম্যানুয়াল মোক এবং এর বাস্তব প্রয়োগ সিঙ্কে রয়েছে তা নিশ্চিত করার জন্য, jest.requireActual(moduleName)আপনার ম্যানুয়াল মোককে ব্যবহার করে এবং এটি রফতানির আগে মক ফাংশনগুলির সাথে সংশোধন করে আসল মডিউলটি ব্যবহার করা কার্যকর হতে পারে ।


4
Fww, আপনি returnবিবৃতিটি সরিয়ে এবং তীর ফাংশন বডিটি প্রথম বন্ধনীতে আবদ্ধ করে আরও জটিল করে তুলতে পারেন : যেমন। jest.mock('./myModule', () => ({ ...jest.requireActual('./myModule'), otherFn: () => {}}))
নিক এফ

4
এটি দুর্দান্ত কাজ করেছে! এটি গ্রহণযোগ্য উত্তর হওয়া উচিত।
JRJurman

4
...jest.requireActualআমার পক্ষে সঠিকভাবে কাজ হয়নি কারণ আমার ...require.requireActual
বাবেলকে ব্যবহার করে

4
আপনি কীভাবে পরীক্ষা করবেন যে otherFunএই ক্ষেত্রে ডাকা হয়েছিল? অনুমানotherFn: jest.fn()
স্টিভুলা

4
@ স্টেভুলা সত্যিকারের ব্যবহারের উদাহরণ দেখানোর জন্য আমি আমার উত্তর আপডেট করেছি। আমি আরও mockReturnValueভালভাবে দেখানোর জন্য পদ্ধতিটি দেখাই যে মক্কৃত সংস্করণটি মূলটির পরিবর্তে কল করা হচ্ছে, তবে আপনি যদি সত্যিই এটি দেখতে চান যে এটি রিটার্নের মূল্যের বিরুদ্ধে জোর না দিয়ে বলা হয়েছে কিনা, আপনি জাস্ট ম্যাচারটি ব্যবহার করতে পারেন .toHaveBeenCalled()
গুলফ্লাম

36
import m from '../myModule';

আমার জন্য কাজ করে না, আমি ব্যবহার করেছি:

import * as m from '../myModule';

m.otherFn = jest.fn();

4
পরীক্ষার পরে আপনি কীভাবে অন্যান্য ফিনের মূল কার্যকারিতা পুনরুদ্ধার করবেন যাতে এটি অন্যান্য পরীক্ষার ক্ষেত্রে হস্তক্ষেপ না করে?
অ্যাকুইটাস

4
আমি মনে করি আপনি প্রতিটি পরীক্ষার পরে উপহাসগুলি সাফ করার জন্য উপহাসকে কনফিগার করতে পারেন? দস্তাবেজগুলি থেকে: "ক্লিয়ারমকস কনফিগারেশন বিকল্প পরীক্ষার মধ্যে স্বয়ংক্রিয়ভাবে মকগুলি সাফ করার জন্য উপলব্ধ" " আপনি clearkMocks: trueজাস্ট প্যাকেজ.জসন কনফিগার করতে পারেন । ফেসবুক.
কোল

4
বিশ্বব্যাপী রাষ্ট্র পরিবর্তন করতে যদি এই জাতীয় সমস্যা হয় তবে আপনি সর্বদা কোনও প্রকারের পরীক্ষা চলকের অভ্যন্তরে মূল কার্যকারিতা সংরক্ষণ করতে পারেন এবং পরীক্ষার পরে এটিকে ফিরিয়ে আনতে পারেন
বাবু

4
কনস্ট আসল; allAl (() => {original = m.otherFn; m.otherFn = jest.fn ();}) after all (())> {m.otherFn = original;}) এটি কাজ করা উচিত, তবে আমি পরীক্ষা করিনি এটি
bobu

তোমাকে অনেক ধন্যবাদ! এটি আমার সমস্যার সমাধান করেছে।
স্লোবোডান ক্রাসাভেভিć

25

দেখে মনে হচ্ছে আমি এই পার্টিতে দেরি করেছি, তবে হ্যাঁ, এটি সম্ভব।

testFnotherFn মডিউলটি ব্যবহার করে কেবল কল করতে হবে ।

যদি testFnকল করতে মডিউলটি ব্যবহার করে otherFnতবে এর জন্য মডিউল রফতানি otherFnউপহাস করা যাবে এবং testFnমোককে কল করবে।


এখানে একটি কার্যকারী উদাহরণ:

myModule.js

import * as myModule from './myModule';  // import myModule into itself

export function otherFn() {
  return 'original value';
}

export function testFn() {
  const result = myModule.otherFn();  // call otherFn using the module

  // do other things

  return result;
}

myModule.test.js

import * as myModule from './myModule';

describe('test category', () => {
  it('tests something about testFn', () => {
    const mock = jest.spyOn(myModule, 'otherFn');  // spy on otherFn
    mock.mockReturnValue('mocked value');  // mock the return value

    expect(myModule.testFn()).toBe('mocked value');  // SUCCESS

    mock.mockRestore();  // restore otherFn
  });
});

4
এটি মূলত ফেসবুকে ব্যবহৃত পদ্ধতির একটি ES6 সংস্করণ এবং এই পোস্টের মাঝখানে একটি ফেসবুক দেব দ্বারা বর্ণিত ।
ব্রায়ান অ্যাডামস

মাইমডুলকে নিজের মধ্যে আমদানি করার পরিবর্তে, কেবল কল করুনexports.otherFn()
andrhamm

4
ES6- এ @andrhamm exportsবিদ্যমান নেই। কলিং exports.otherFn()এখনই কাজ করে কারণ ES6 পূর্ববর্তী মডিউল সিনট্যাক্সে সংকলিত হচ্ছে, তবে ES6 স্থানীয়ভাবে সমর্থিত হলে এটি ভেঙে যাবে।
ব্রায়ান অ্যাডামস

এই মুহুর্তে এই সঠিক সমস্যাটি রয়েছে এবং আমি নিশ্চিত যে এর আগেও আমি এই সমস্যার মুখোমুখি হয়েছি। আমাকে প্রচুর রফতানি মুছে ফেলতে হয়েছে tree আমি এর কোন প্রভাব আছে কিনা তা দেখতে পাব, তবে এটি এতটা হ্যাকি বলে মনে হচ্ছে। আমি এই সমস্যাটি বেশ কয়েকবার এসেছি এবং অন্যান্য উত্তরের মত বলেছে, বাবেল -প্লাগইন- রিভাইয়ার বা আরও ভাল, এনপিএমজেএস / প্যাকেজ / স্ক্রিমমক যা আমি অবশ্যই নিশ্চিত যে উপরেরটিও করতে পারে।
এস্ট্রিড্যাক্স

ফিরতি মূল্যের পরিবর্তে বিদ্রূপ করা, ঠোকা ঠেকানো কি সম্ভব? সম্পাদনা করুন: আপনি পারেন, এখানে স্ট্যাকওভারফ্লো.com
বড় অর্থ

10

স্থানান্তরিত কোডটি বাবেলকে otherFn()উল্লেখ করা বাধ্যতামূলক পুনরুদ্ধার করতে অনুমতি দেবে না । আপনি যদি কোনও ফাংশন সমাপ্তি ব্যবহার করেন তবে আপনার উপহাস করা সম্ভব হবে otherFn()

// myModule.js
exports.otherFn = () => {
  console.log('do something');
}

exports.testFn = () => {
  exports.otherFn();

  // do other things
}

 

// myModule.test.js
import m from '../myModule';

m.otherFn = jest.fn();

তবে পূর্ববর্তী মন্তব্যে @ কেন্টকডডস যেমন উল্লেখ করেছেন, আপনি সম্ভবত বিদ্রূপ করতে চাইবেন না otherFn()। বরং কেবল একটি নতুন স্পেক লিখুন otherFn()এবং এটি যে কোনও প্রয়োজনীয় কল করছে তা উপহাস করে।

সুতরাং উদাহরণস্বরূপ, যদি otherFn()একটি HTTP অনুরোধ করা হয় ...

// myModule.js
exports.otherFn = () => {
  http.get('http://some-api.com', (res) => {
    // handle stuff
  });
};

এখানে, আপনি http.getআপনার বিদ্রূপক প্রয়োগগুলির উপর ভিত্তি করে আপনার দাবিগুলি উপহাস এবং আপডেট করতে চান ।

// myModule.test.js
jest.mock('http', () => ({
  get: jest.fn(() => {
    console.log('test');
  }),
}));

4
যদি অন্যান্যFn এবং testFn অন্যান্য বেশ কয়েকটি মডিউল দ্বারা ব্যবহৃত হয় তবে কী হবে? আপনার কি সমস্ত টেস্ট ফাইলগুলিতে এই 2 টি মডিউল ব্যবহার করে (তবে স্ট্যাকের গভীরতর) কোনও http মক সেটআপ করতে হবে? এছাড়াও, যদি আপনার ইতিমধ্যে টেস্টএফএন এর জন্য একটি পরীক্ষা থাকে তবে কেন মডিউল টেস্টএফএন ব্যবহার করে সরাসরি HTTP এর পরিবর্তে পরীক্ষা-নিরীক্ষা করবেন না?
21

4
সুতরাং যদি otherFnএটি ভাঙা হয় তবে সেই পরীক্ষার উপর নির্ভর করে সমস্ত পরীক্ষায় ব্যর্থ হবে। এছাড়াও যদি otherFnআপনার ভিতরে 5 টি আইফএস থাকে তবে আপনার testFnএটি পরীক্ষা করার প্রয়োজন হতে পারে যে আপনি এই সমস্ত সাব কেসের জন্য ভাল কাজ করছেন। আপনার এখন পরীক্ষা করার জন্য আরও অনেক কোড পাথ থাকবে।
Totty.js

6

আমি জানি এটি অনেক আগে জিজ্ঞাসা করা হয়েছিল, তবে আমি কেবল এই খুব পরিস্থিতি নিয়ে এসেছি এবং অবশেষে এমন একটি সমাধান খুঁজে পেয়েছি যা কাজ করবে। তাই আমি ভেবেছিলাম আমি এখানে ভাগ করে নেব।

মডিউলটির জন্য:

// myModule.js

export function otherFn() {
  console.log('do something');
}

export function testFn() {
  otherFn();

  // do other things
}

আপনি নিম্নলিখিতগুলিতে পরিবর্তন করতে পারেন:

// myModule.js

export const otherFn = () => {
  console.log('do something');
}

export const testFn = () => {
  otherFn();

  // do other things
}

ফাংশন পরিবর্তে ধ্রুবক হিসাবে তাদের রফতানি। আমি বিশ্বাস করি জাভাস্ক্রিপ্টে উত্তোলন করা এবং ব্যবহার করা এই constআচরণটির প্রতিরোধ করে।

তারপরে আপনার পরীক্ষায় আপনার নীচের মতো কিছু থাকতে পারে:

import * as myModule from 'myModule';


describe('...', () => {
  jest.spyOn(myModule, 'otherFn').mockReturnValue('what ever you want to return');

  // or

  myModule.otherFn = jest.fn(() => {
    // your mock implementation
  });
});

আপনার বিদ্রূপগুলি এখন যেমনটি আশা করবেন তেমনই কাজ করা উচিত।


2

আমি এখানে যে উত্তরগুলি পেয়েছি তার মিশ্রণ দিয়ে আমার সমস্যাটি সমাধান করেছি:

myModule.js

import * as myModule from './myModule';  // import myModule into itself

export function otherFn() {
  return 'original value';
}

export function testFn() {
  const result = myModule.otherFn();  // call otherFn using the module

  // do other things

  return result;
}

myModule.test.js

import * as myModule from './myModule';

describe('test category', () => {
  let otherFnOrig;

  beforeAll(() => {
    otherFnOrig = myModule.otherFn;
    myModule.otherFn = jest.fn();
  });

  afterAll(() => {
    myModule.otherFn = otherFnOrig;
  });

  it('tests something about testFn', () => {
    // using mock to make the tests
  });
});

0

এখানে প্রথম উত্তরের উপরে, আপনি ব্যাবিল-প্লাগইন-রিওয়ায়ারটি আমদানিকৃত নামকৃত কার্যটিও উপহাস করতে পারেন to আপনার জন্য কৃত্রিম অধ্যায় চেক আউট করতে পারেন নামে ফাংশন নতুন ওয়্যারিং

এখানে আপনার পরিস্থিতির জন্য অবিলম্বে একটি সুবিধা হ'ল আপনার ফাংশন থেকে অন্য ফাংশনটিকে কীভাবে কল করবেন তার পরিবর্তন করার দরকার নেই।


নোড.জেএস নিয়ে কাজ করতে বাবেল-প্লাগইন-রিওয়ায়ার কীভাবে কনফিগার করবেন?
তৈমুর গিলারী
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.