使用Mocha时Catch-22递归节点模块爆炸 [英] Catch-22 recursive Node modules blowing up when using Mocha

查看:131
本文介绍了使用Mocha时Catch-22递归节点模块爆炸的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在研究使用一些自定义Node.js模块的项目.我创建了一个帮助程序"模块,该模块可帮助加载一些帮助程序方法:

I've been working on a project that uses some custom Node.js modules. I've created a 'helpers' module that assists with loading some helper methods:

/helpers/index.js:

var mutability = require('./mutability'),
    cb = require('./cb'),
    build = require('./build'),
    userAgent = require('./userAgent'),
    is = require('./is'),
    query = require('./query'),
    config = require('./config'),
    _ = require('underscore')

module.exports = _.extend({
    cb: cb,
    build: build,
    userAgent: userAgent,
    is: is,
    query: query,
    config: config
}, mutability)

为了娱乐,mutability.js是:

'use strict'

module.exports = {
    setReadOnly: function(obj, key) {
        // whatever
        return obj
    },
    setWritable: function(obj, key) {
        // whatever
        return obj
    }
}

我的一个模块build,需要一个类来进行某种类型检查:

One of my modules, build, requires a class to do some type checking:

/helpers/build.js

'use strict'

var urljoin = require('url-join'),
    config = require('./config'),
    cb = require('./cb'),
    Entity = require('../lib/entity'),
    _ = require('underscore')

module.exports = {
    url: function(options) {
        return urljoin(
            config.baseUrl,
            options.client.orgId,
            options.client.appId,
            options.type, (typeof options.uuidOrName === 'string') ? options.uuidOrName : ""
        )
    },
    GET: function(options) {
        options.type = options.type || args[0] instanceof Entity ? args[0]._type : args[0]
        options.query = options.query || args[0] instanceof Entity ? args[0] : undefined
        return options
    }
}

然后Entity然后需要helpers:

/lib/entity.js

'use strict'

var helpers = require('../helpers'),
    ok = require('objectkit'),
    _ = require('underscore')

var Entity = function(object) {
    var self = this

    _.extend(self, object)

    helpers.setReadOnly(self, ['uuid'])

    return self
}

module.exports = Entity

无论出于何种原因,当我在Mocha上运行此命令时,我都会以{}的身份登出helpers,并且Mocha引发:

For whatever reason, when I run this with Mocha, I get helpers logging out as {} and Mocha throws:

Uncaught TypeError: helpers.setReadOnly is not a function

当我直接使用node运行/lib/entity.js时,它将打印正确的模块.是什么赋予了?摩卡为何爆炸?

When I run /lib/entity.js directly with node, it prints the proper module. What gives? Why is Mocha blowing up?

推荐答案

您正确的问题是您在index.jsentity.js之间存在循环依赖关系.

You are correct that the issue is your circular dependency between index.js and entity.js.

您的依存关系图如下所示(带有标准化路径),其中每个箭头都是require语句:

Your dependency graph looks like this (with normalised paths) where each arrow is a require statement:

/helpers/index.js -> /helpers/build.js -> /lib/entity.js -> /helpers/index.js

当模块required在节点module.exports中被初始化为空对象时.

When a module is required in Node module.exports is initialised to an empty object.

当您具有循环依赖项时,有可能将此默认对象之前返回到另一个模块,因为您的代码已运行以实际设置module.exports = ...;(因为JavaScript是同步的).

When you have a circular dependency then it's possible that this default object is returned to another module before your code has run to actually set module.exports = ...; (because JavaScript is synchronous).

这就是您正在发生的情况:/lib/entity.js在index.js定义它为module.exports = _.extend(...)之前,已从/helpers/index.js接收默认的导出对象.

This is what is happening in your case: /lib/entity.js is receiving the default exports object from /helpers/index.js before index.js has defined it's module.exports = _.extend(...).

要修复此问题,您需要确保扩展返回到/lib/entity.js的同一对象,而不是用新的实例替换它:

To fix it you need to make sure that you extend the same object that has been returned to /lib/entity.js, instead of replacing it with a new instance:

// Extend `module.exports` instead of replacing it with a new object.
module.exports = _.extend(
    module.exports,
    {
        cb: cb,
        build: build,
        userAgent: userAgent,
        is: is,
        query: query,
        config: config
    },
    mutability
);

但是,通常最好避免循环依赖.

However, it's generally best to avoid circular dependencies if possible.

这篇关于使用Mocha时Catch-22递归节点模块爆炸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆