浅析Node.js中使用依赖注入的相关问题及解决方法

JavaScript021

浅析Node.js中使用依赖注入的相关问题及解决方法,第1张

这篇文章主要介绍了浅析Node.js中使用依赖注入的相关问题及解决方法,Node.js是一个将JavaScript应用运行于服务器端的框架,需要的朋友可以参考下

最近,我转向使用依赖注入来帮助理解分离代码的简单途径,并有助测试。然而,Node.js中的模块依赖Node提供的系统API,这很难判断私有依赖被恰当的使用。一般的依赖注入很难在这种情况下使用,但现在不要放弃希望。

requireCauses

问题

Node.js很容易依照需求导入依赖。它运行的很好,并且比AMD模式加载器例如RequireJS要简单。当我们模拟那些依赖的时候问题就来了。如果Node.js中模型的加载是受控的,我们怎么做才能控制让伪对象在测试期间被使用到?我们可以使用Node的vm模式,通过vm我们可以再新的上下文中加载模型。运行在新的上下文中,我们可以控制需求反射出模型的方法。

解决方案

谢谢这篇文章,

现在可以给你提供一个相当不错的解决方案.

代码在下面:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

var

vm

=

require('vm')

var

fs

=

require('fs')

var

path

=

require('path')

/**

*

Helper

for

unit

testing:

*

load

module

with

mocked

dependencies

*

allow

accessing

private

state

of

the

module

*

*

@param

{string}

filePath

Absolute

path

to

module

(file

to

load)

*

@param

{Object=}

mocks

Hash

of

mocked

dependencies

*/

exports.loadModule

=

function(filePath,

mocks)

{

mocks

=

mocks

||

{}

//

this

is

necessary

to

allow

relative

path

modules

within

loaded

file

//

i.e.

requiring

./some

inside

file

/a/b.js

needs

to

be

resolved

to

/a/some

var

resolveModule

=

function(module)

{

if

(module.charAt(0)

!==

'.')

return

module

return

path.resolve(path.dirname(filePath),

module)

}

var

exports

=

{}

var

context

=

{

require:

function(name)

{

return

mocks[name]

||

require(resolveModule(name))

},

console:

console,

exports:

exports,

module:

{

exports:

exports

}

}

vm.runInNewContext(fs.readFileSync(filePath),

context)

return

context

}

你也可以在

这里

下载代码片段

.

虽然在不是在文章发布最多的代码,

他仍然可以使用一些解释.

当我们测试时,

我们要加载这个模块进入测试,

使用theloadModulefunction代替ofrequire加载模块测试.

第一个参数filePath指定了我们要测试模型的查找位置。第二个参数mocks包含一个对象,对象的属性名称要和我们尝试require的模型的名称相匹配。那些属性指定的值就是伪对象,用来代替一般被require的模型。

本质上看就是用vm来加载和运行模型在另一个上下文中。换句话说,我们重建了全局变量(例如require和exports)以便我们能控制它们。需要注意的是我们编写了一个可用的新require函数。所做一切就是检查一下用执行的名字是否有一个模拟的依赖,如果每日有,我就就把它委托给那个常用的require函数。

使用模块加载器的例子

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

var

fs

=

require('fs')

module.exports

=

{

//

Do

something

with

`fs`

}

想象一下这个很酷,对吗?不管怎样,现在我们测试那个模块,但是我们要模拟fs来看看它是怎么在内部使用的。

//

Jasmine's

syntax

http://pivotal.github.com/jasmine/

describe('someModule',

function()

{

var

loadModule

=

require('module-loader').loadModule

var

module,

fsMock

beforeEach(function()

{

fsMock

=

{

//

a

mock

for

`fs`

}

//

load

the

module

with

mock

fs

instead

of

real

fs

module

=

loadModule('./web-server.js',

{fs:

fsMock})

})

it('should

work',

function()

{

//

a

test

that

utilizes

the

fact

that

we

can

now

control

`fs`

})

})

AngularJS 在实际应用中优点:

模板功能强大丰富,并且是声明式的,自带了丰富的Angular指令;

是一个比较完善的前端MV*框架,包含模板,数据双向绑定,路由,模块化,服务,过滤器,依赖注入等所有功能;

自定义Directive,比jQuery插件还灵活,但是需要深入了解Directive的一些特性,简单的封装容易,复杂一点官方没有提供详细的介绍文档,可以通过阅读源代码来找到某些我们需要的东西;

ng模块化比较大胆的引入了Java的一些东西(依赖注入),能够很容易的写出可复用的代码,对于敏捷开发的团队来说非常有帮助,即使UI变化很大,而且产品更新迭代,但是js的代码基本上却很少改动。

补充:Angular支持单元测试和e2e-testing。

AngularJS 在实际应用中缺点:

验证功能错误信息显示比较薄弱,需要写很多模板标签,没有jQuery Validate方便,所以我们自己封装了验证的错误信息提示;

ngView只能有一个,不能嵌套多个视图,虽然有 angular-ui/ui-router · GitHub 解决,但是貌似ui-router 对于URL的控制不是很灵活,必须是嵌套式的;

对于特别复杂的应用场景,貌似性能有点问题,特别是在Windows下使用chrome浏览器;

这没有完美兼容低版本,升级之后可能会导致一个兼容性的BUG;

ng提倡在控制器里面不要有操作DOM的代码,对于一些jQuery 插件的使用,如果想不破坏代码的整洁性,需要写一些directive去封装插件,但是现在有很多插件的版本已经支持Angular了;

Angular 太笨重了,没有让用户选择一个轻量级的版本,;

使用的人多才会暴露更多的问题,一起为这些问题寻找解决方案是一个社区的良性趋势,选择Angular,的确使开发效率大大提高。