নোড.জেএস মডিউলে কোনও অভ্যন্তরীণ (অ-রফতানি) ফাংশন অ্যাক্সেস এবং পরীক্ষার পদ্ধতি কীভাবে?


178

আমি নোডেজগুলিতে কীভাবে অভ্যন্তরীণ (যেমন রফতানি করা হয় না) ফাংশনগুলি পরীক্ষা করতে হবে (অগ্রাধিকারে মোচা বা জুঁই দিয়ে) কীভাবে তা পরীক্ষা করার চেষ্টা করছি। আর আমার কোন ধারণা নেই!

ধরা যাক আমার মতো একটি মডিউল রয়েছে:

function exported(i) {
   return notExported(i) + 1;
}

function notExported(i) {
   return i*2;
}

exports.exported = exported;

এবং নিম্নলিখিত পরীক্ষা (মোচা):

var assert = require('assert'),
    test = require('../modules/core/test');

describe('test', function(){

  describe('#exported(i)', function(){
    it('should return (i*2)+1 for any given i', function(){
      assert.equal(3, test.exported(1));
      assert.equal(5, test.exported(2));
    });
  });
});

notExportedফাংশনটি বাস্তবে রফতানি না করে পরীক্ষা করার কোনও উপায় আছে যেহেতু এটি উন্মোচিত হওয়ার অর্থ নয়?


1
একটি নির্দিষ্ট পরিবেশে যখন হতে পারে পরীক্ষার জন্য কেবল কার্যগুলি প্রকাশ করতে পারে? আমি এখানে স্ট্যান্ডার্ড পদ্ধতি জানি না।
লোগানফস্মিথ

উত্তর:


240

বৈদ্যুতিক তার লাগানো মডিউল স্পষ্টভাবে উত্তর।

অপ্রমাণিত ফাংশন অ্যাক্সেস করতে এবং মোচা ব্যবহার করে এটি পরীক্ষা করার জন্য আমার কোডটি এখানে's

application.js:

function logMongoError(){
  console.error('MongoDB Connection Error. Please make sure that MongoDB is running.');
}

test.js:

var rewire = require('rewire');
var chai = require('chai');
var should = chai.should();


var app = rewire('../application/application.js');


logError = app.__get__('logMongoError'); 

describe('Application module', function() {

  it('should output the correct error', function(done) {
      logError().should.equal('MongoDB Connection Error. Please make sure that MongoDB is running.');
      done();
  });
});

2
এটি একেবারে শীর্ষ উত্তর হওয়া উচিত। এটির জন্য NODE_ENV নির্দিষ্ট রফতানীর সাথে বিদ্যমান সমস্ত মডিউলগুলি পুনরায় লেখার প্রয়োজন হয় না বা এটি মডিউলটিতে পাঠ্য হিসাবে জড়িতও না।
আদম ইয়স্ট

সুন্দর সমাধান। আপনার পরীক্ষার কাঠামোর মধ্যে এটি গুপ্তচরদের সাথে আরও সংহত করা এবং সংহত করা সম্ভব। জুঁইয়ের সাথে কাজ করে, আমি এই কৌশলটি চেষ্টা করেছিলাম ।
ফ্রাঙ্কো

2
দুর্দান্ত সমাধান। বাবেল ধরণের লোকদের জন্য কি কোনও ওয়ার্কিং সংস্করণ রয়েছে?
চার্লস মেরিয়াম

2
বৈদ্যুতিক তার লাগানো ব্যবহার বিদ্রূপের বিষয় রূপে গ্রহণ এবং TS-বিদ্রূপের বিষয় রূপে গ্রহণ (টাইপ করা বিষয়) আমি নিম্নলিখিত ত্রুটি পেতে সাথে Cannot find module '../../package' from 'node.js'। তুমি কি এটা দেখেছ?
ক্লু

2
রিওয়ায়ারের সাথে উপহাসের সাথে সামঞ্জস্যের সমস্যা রয়েছে। জাস্ট কভারেজ রিপোর্টে রিভাইয়ার থেকে ডাকা ফাংশনগুলি বিবেচনা করবে না। যা কিছুটা হলেও উদ্দেশ্যকে পরাস্ত করে।
রোব্রস0606

10

কৌশলটি হ'ল NODE_ENVপরিবেশের পরিবর্তনশীলকে এর মতো কিছুতে সেট করা testএবং তারপরে শর্তাধীন এটি রফতানি করা।

ধরে নিই যে আপনি বিশ্বব্যাপী মোচা ইনস্টল করেননি, আপনার অ্যাপ্লিকেশন ডিরেক্টরিটির মূলটিতে একটি মেকফাইল থাকতে পারে যাতে নিম্নলিখিতটি থাকে:

REPORTER = dot

test:
    @NODE_ENV=test ./node_modules/.bin/mocha \
        --recursive --reporter $(REPORTER) --ui bbd

.PHONY: test

এই মেক ফাইলটি মোচা চালানোর আগে NODE_ENV সেট আপ করে। তারপরে আপনি make testকমান্ড লাইনে আপনার মোচা পরীক্ষা চালাতে পারেন ।

এখন, আপনি শর্তাধীন আপনার ফাংশনটি রফতানি করতে পারেন যা সাধারণত আপনার মোচা পরীক্ষা চলাকালীন রফতানি হয় না:

function exported(i) {
   return notExported(i) + 1;
}

function notExported(i) {
   return i*2;
}

if (process.env.NODE_ENV === "test") {
   exports.notExported = notExported;
}
exports.exported = exported;

অন্য উত্তরটি ফাইলটি মূল্যায়নের জন্য একটি ভিএম মডিউল ব্যবহার করার পরামর্শ দিয়েছিল, তবে এটি কার্যকর হয় না এবং রফতানি সংজ্ঞায়িত নয় বলে উল্লেখ করে একটি ত্রুটি ছুড়ে দেয়।


8
এটি হ্যাকের মতো মনে হচ্ছে, NODE_ENV ব্লক না করে আসলেই অভ্যন্তরীণ (অ-রফতানি করা) ফাংশনগুলি পরীক্ষা করার কোনও উপায় নেই?
রায়ানহিরশ

2
এটা বেশ বাজে। এই সমস্যাটি সমাধান করার সর্বোত্তম উপায় এটি হতে পারে না।
এনপিভ

7

সম্পাদনা করুন:

মডিউলটি ব্যবহার করে লোড করা vmঅপ্রত্যাশিত আচরণের কারণ হতে পারে (যেমন instanceofঅপারেটর আর এমন মডিউলে তৈরি হওয়া বস্তুগুলির সাথে আর কাজ করে না কারণ গ্লোবাল প্রোটোটাইপগুলি সাধারণত লোড হওয়া মডিউলটিতে ব্যবহৃত থেকে আলাদা require)। আমি আর নীচের কৌশলটি ব্যবহার করি না এবং পরিবর্তে রিওয়্যার মডিউলটি ব্যবহার করি । এটি আশ্চর্যজনকভাবে কাজ করে। আমার মূল উত্তরটি এখানে:

শ্রোশের উত্তর নিয়ে বিশদ বিবরণ ...

এটি কিছুটা কড়া মনে হচ্ছে, তবে আমি একটি সাধারণ "test_utils.js" মডিউল লিখেছি যা আপনাকে আপনার অ্যাপ্লিকেশন মডিউলগুলিতে শর্তাধীন রফতানি না করে যা করতে চান তা করতে দেয়:

var Script = require('vm').Script,
    fs     = require('fs'),
    path   = require('path'),
    mod    = require('module');

exports.expose = function(filePath) {
  filePath = path.resolve(__dirname, filePath);
  var src = fs.readFileSync(filePath, 'utf8');
  var context = {
    parent: module.parent, paths: module.paths, 
    console: console, exports: {}};
  context.module = context;
  context.require = function (file){
    return mod.prototype.require.call(context, file);};
  (new Script(src)).runInNewContext(context);
  return context;};

নোড মডিউলটির গবাল moduleঅবজেক্টের সাথে আরও কিছু জিনিস অন্তর্ভুক্ত রয়েছে যা উপরের বস্তুতেও যেতে পারে context, তবে এটি কাজ করার জন্য আমার এটি ন্যূনতম সেট need

এখানে মোচা বিডিডি ব্যবহারের একটি উদাহরণ রয়েছে:

var util   = require('./test_utils.js'),
    assert = require('assert');

var appModule = util.expose('/path/to/module/modName.js');

describe('appModule', function(){
  it('should test notExposed', function(){
    assert.equal(6, appModule.notExported(3));
  });
});

2
আপনি কীভাবে একটি অ-রফতানি ক্রিয়াকলাপটি ব্যবহার করে একটি উদাহরণ দিতে পারেন rewire?
ম্যাথিয়াস

1
ওহে ম্যাথিয়াস, আমি আমার উত্তরে হুবহু এক উদাহরণ দিয়েছি। আপনি যদি এটি পছন্দ করেন, আমার upwote হতে পারে আমার কিছু প্রশ্ন? :) আমার প্রায় সব প্রশ্ন 0 এ বসে আছে এবং স্ট্যাকওভারফ্লো আমার প্রশ্নগুলি হিম করার বিষয়ে ভাবছে। এক্স_এক্স
অ্যান্থনি

2

জুঁই নিয়ে কাজ করা, আমি সাথে আরো গভীর যাওয়ার চেষ্টা সমাধান এন্থনি: Mayfield দ্বারা প্রস্তাবিত উপর ভিত্তি করে বৈদ্যুতিক তার লাগানো

আমি নিম্নলিখিত ফাংশনটি বাস্তবায়ন করেছি ( সাবধানতা : এখনও পুরোপুরি পরীক্ষিত হয়নি, কেবল সম্ভাব্য কৌশল হিসাবে ভাগ করা হয়েছে) :

function spyOnRewired() {
    const SPY_OBJECT = "rewired"; // choose preferred name for holder object
    var wiredModule = arguments[0];
    var mockField = arguments[1];

    wiredModule[SPY_OBJECT] = wiredModule[SPY_OBJECT] || {};
    if (wiredModule[SPY_OBJECT][mockField]) // if it was already spied on...
        // ...reset to the value reverted by jasmine
        wiredModule.__set__(mockField, wiredModule[SPY_OBJECT][mockField]);
    else
        wiredModule[SPY_OBJECT][mockField] = wiredModule.__get__(mockField);

    if (arguments.length == 2) { // top level function
        var returnedSpy = spyOn(wiredModule[SPY_OBJECT], mockField);
        wiredModule.__set__(mockField, wiredModule[SPY_OBJECT][mockField]);
        return returnedSpy;
    } else if (arguments.length == 3) { // method
        var wiredMethod = arguments[2];

        return spyOn(wiredModule[SPY_OBJECT][mockField], wiredMethod);
    }
}

এর মতো একটি ফাংশন দিয়ে আপনি উভয় পদ্ধতিতে রফতানি না হওয়া অবজেক্টস এবং অ-রফতানি শীর্ষ স্তরের ফাংশনগুলির উপর নজর রাখতে পারেন:

var dbLoader = require("rewire")("../lib/db-loader");
// Example: rewired module dbLoader
// It has non-exported, top level object 'fs' and function 'message'

spyOnRewired(dbLoader, "fs", "readFileSync").and.returnValue(FULL_POST_TEXT); // method
spyOnRewired(dbLoader, "message"); // top level function

তারপরে আপনি এগুলির মতো প্রত্যাশা সেট করতে পারেন:

expect(dbLoader.rewired.fs.readFileSync).toHaveBeenCalled();
expect(dbLoader.rewired.message).toHaveBeenCalledWith(POST_DESCRIPTION);

1

আমি একটি বেশ সহজ উপায় খুঁজে পেয়েছি যা আপনাকে পরীক্ষার মধ্যে থেকে সেই অভ্যন্তরীণ ফাংশনগুলি পরীক্ষা, গুপ্তচর এবং উপহাস করার অনুমতি দেয়:

ধরা যাক আমাদের মতো নোড মডিউল রয়েছে:

mymodule.js:
------------
"use strict";

function myInternalFn() {

}

function myExportableFn() {
    myInternalFn();   
}

exports.myExportableFn = myExportableFn;

যদি আমরা এখন এটির উত্পাদনে রফতানি না করে পরীক্ষা করতে এবং গুপ্তচরবৃত্তি করতে চাই এবং উপহাস করতে চাই তবে আমাদের এই জাতীয় ফাইলটি উন্নত করতে হবে:myInternalFn

my_modified_module.js:
----------------------
"use strict";

var testable;                          // <-- this is new

function myInternalFn() {

}

function myExportableFn() {
    testable.myInternalFn();           // <-- this has changed
}

exports.myExportableFn = myExportableFn;

                                       // the following part is new
if( typeof jasmine !== "undefined" ) {
    testable = exports;
} else {
    testable = {};
}

testable.myInternalFn = myInternalFn;

এখন আপনি পরীক্ষা করতে পারেন, গুপ্তচর এবং ম্যাক myInternalFnকরতে পারেন যেখানেই আপনি এটি ব্যবহার করেন testable.myInternalFnএবং উত্পাদনে এটি রফতানি হয় না


0

আপনি ভিএম মডিউল ব্যবহার করে একটি নতুন প্রসঙ্গ তৈরি করতে পারেন এবং এতে জেএস ফাইলটি বিভক্ত করতে পারেন, যেমন repl এর মতো করে। তারপরে এটির ঘোষণা অনুসারে আপনার কাছে অ্যাক্সেস রয়েছে।


0

এটি অনুশীলনের প্রস্তাবিত নয়, তবে আপনি rewire@ অ্যান্টাইন এর পরামর্শ অনুযায়ী ব্যবহার করতে না পারলে আপনি সর্বদা কেবল ফাইলটি পড়তে এবং ব্যবহার করতে পারেন eval()

var fs = require('fs');
const JsFileString = fs.readFileSync(fileAbsolutePath, 'utf-8');
eval(JsFileString);

উত্তরাধিকার ব্যবস্থার জন্য ক্লায়েন্ট-সাইড জেএস ফাইলগুলির ইউনিট পরীক্ষা করার সময় আমি এই দরকারী পেয়েছি।

জেএস ফাইলগুলি windowকোনও বিবৃতি require(...)এবং module.exportsবিবৃতি ছাড়াই প্রচুর গ্লোবাল ভেরিয়েবল সেট আপ করবে (ওয়েবপ্যাক বা ব্রাউজারফাইয়ের মতো কোনও মডিউল বান্ডার নেই যেহেতু এই বিবৃতিগুলি সরিয়ে দেওয়ার জন্য)।

সম্পূর্ণ কোডবেসটি রিফ্যাক্টরের পরিবর্তে এটি আমাদের ক্লায়েন্ট-সাইড জেএসে ইউনিট পরীক্ষাগুলি সংহত করার অনুমতি দেয়।

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