Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0af1dcb

Browse files
committed
- changed API
- introduced __set__ and __get__ to rewired modules
1 parent75f6a77 commit0af1dcb

26 files changed

+689
-417
lines changed

‎README.md

Lines changed: 72 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ rewire
22
=====
33
**Dependency injection for node.js applications**.
44

5-
rewire allows you to modify the behaviour of modules for better unit testing. You may
5+
rewire adds a special setter and getter that allow you to modify the behaviour of modules
6+
for better unit testing. You may
67

78
- introduce mocks for other modules
89
- leak private variables
9-
- override variables within the module
10-
- inject your own scripts
10+
- override variables within the module.
1111

1212
rewire does**not** load the file and eval the contents to emulate node's require mechanism. In fact it uses node's own require to load the module. Thus your module behaves exactly the same in your test environment as under regular circumstances (except your modifications).
1313

@@ -22,8 +22,7 @@ Installation
2222
`npm install rewire`
2323

2424
**For older node versions:**<br />
25-
rewire is tested with node 0.6.x. I recommend to run the unit tests via`mocha` in the rewire-folder before
26-
using rewire with older node versions.
25+
rewire is tested with node 0.6.x. I recommend to run the unit tests via`mocha` in the rewire-folder before using rewire with older node versions.
2726

2827
-----------------------------------------------------------------
2928
<br />
@@ -34,146 +33,115 @@ Examples
3433
```javascript
3534
var rewire=require("rewire");
3635

37-
// rewire acts exactly like require when omitting all other params
38-
rewire("./myModuleA.js")===require("./myModuleA.js");// = true
39-
```
4036

41-
###Mocks
42-
```javascript
43-
// You can introduce your own mocks for modules that are required:
44-
rewiredModule=rewire("./myModuleA.js", {
45-
"fs": {
46-
readFile:function (path,encoding,cb) {cb(null,"Success!"); }
47-
},
48-
"../path/to/moduleB.js": myMockForModuleB
37+
// rewire acts exactly like require.
38+
var myRewiredModule=rewire("../lib/myModule.js");
39+
myRewiredModule===require("../lib/myModule.js");// = true
40+
41+
42+
// Your module will now export a special setter and getter for private variables.
43+
myModule.__set__("myPrivateVar",123);
44+
myModule.__get__("myPrivateVar");// = 123
45+
46+
47+
// This allows you to mock almost everything within the module e.g. the fs-module.
48+
// Just pass the variable name as first parameter and your mock as second.
49+
myModule.__set__("fs", {
50+
readFile:function (path,encoding,cb) {
51+
cb(null,"Success!");
52+
}
53+
});
54+
myModule.readSomethingFromFileSystem(function (err,data) {
55+
console.log(data);// = Success!
4956
});
50-
// The rewired module will now use your mocks instead of fs
51-
// and moduleB.js. Just make sure that the path is exactly as
52-
// in myModuleA.js required.
53-
```
5457

55-
###Injections
56-
```javascript
57-
// You can inject your own mocks for internal or global objects.
58-
// These injections are only visible within the module.
59-
rewiredModule=rewire("./myModuleA.js",null, {
58+
59+
// All later requires will now return the module with the mock.
60+
myModule===require("./myModule.js");// = true
61+
62+
63+
// You can set different variables with one call.
64+
myModule.__set__({
65+
fs: fsMock,
66+
http: httpMock,
67+
someOtherVar:"hello"
68+
});
69+
70+
71+
// You may also override globals. These changes are only within the module,
72+
// so you don't have to be afraid that other modules are influenced by your mock.
73+
myModule.__set__({
6074
console: {
6175
log:function () {/* be quiet*/ }
6276
},
63-
process: { argv: ["some","other","args"] },
64-
__filename:"some/other/dir"
77+
process: {
78+
argv: ["testArg1","testArg2"]
79+
}
6580
});
6681

67-
// This will inject
68-
// var console = {log: function () { /* be quiet */ }};
69-
// var process = {argv: ["some", "other", "args"]};
70-
// var __filename = "some/other/dir";
71-
// at the end of the module.
7282

73-
// You can also pass a script to inject at the end
74-
rewiredModule=rewire("./myModuleA.js",null,"console.log('hello');");
75-
// This will print "hello" when the module loads
76-
```
83+
// But be careful, if you do something like this you'll change your global
84+
// console instance.
85+
myModule.__set__("console.log",function () {/* be quiet*/ });
7786

78-
###Leaks
79-
```javascript
80-
// You can expose private variables for unit tests
81-
rewiredModule=rewire("./myModuleA.js",null,null, ["myVar1","myVar2");
8287

83-
//This will inject
84-
// module.exports.__ = {myVar1: myVar1, myVar2: myVar2}
85-
// at the end of the module.
88+
//By getting private variables you can test for instance if your
89+
// module is in a specific state
90+
assert.ok(myModule.__get__("currentState")==="idle");
8691

87-
// You can access now your private variables under the special.__-object
88-
console.log(rewiredModule.__.myVar1);
89-
console.log(rewiredModule.__.myVar2);
90-
```
9192

92-
###Cache
93-
```javascript
94-
// You can disable caching of the rewired module. Any require()-calls will
95-
// now return the original module again instead of the rewired.
96-
// Caching is enabled by default.
97-
rewire("./myModuleA.js",null,null,null,false)===require("./myModuleA.js");
98-
// = false
93+
// You can also disable caching when loading the rewired module. All
94+
// subsequent calls of require() will than return the original module again.
95+
rewire("./myModule.js",false)===require("./myModule.js");// = false
96+
97+
98+
// Every call of rewire returns a new instance and overwrites the old
99+
// one in the module cache.
100+
rewire("./myModule.js")===rewire("./myModule.js");// = false
99101

100-
// You can also delete all rewired modules from the cache by one call.
102+
103+
// If you want to remove all your rewired modules from the
104+
// cache just call rewire.reset().
105+
// Do this before every unit test to ensure a clean testing environment.
101106
rewire.reset();
102-
// You should call this after every unit test to ensure a clean test environment.
103107
```
104108

105109
-----------------------------------------------------------------
106110
<br />
107111

108112
##API
109113

110-
**rewire(***filename,mocks, injections, leaks,cache***)**
114+
**rewire(***filename, cache***): {RewiredModule}**
111115

112116
-*{!String} filename*: <br/>
113117
Path to the module that shall be rewired. Use it exactly like require().
114118

115-
-*{Object} mocks (optional)*: <br/>
116-
An object with module mocks. Keys should reflect the required path of the module.
117-
118-
-*{Object|String} injections (optional)*: <br />
119-
If you pass an object, all keys of the object will be`var`s within the module. You can also eval a string.
120-
121-
-*{Array&lt;String&gt;} leaks (optional)*: <br/>
122-
An array with variable names that should be exported. These variables are accessible via`myModule.__`.
123-
124119
-*{Boolean=true} cache (optional)*: <br />
125120
Indicates whether the rewired module should be cached by node so subsequent calls of`require()` will
126121
return the rewired module. Further calls of`rewire()` will always overwrite the cache.
127122

128-
Returns the rewired module.
129-
130123
**rewire.reset()**
131124

132125
Removes all rewired modules from`require.cache`. Every`require()` will now return the original module again.
133126

134-
-----------------------------------------------------------------
135-
<br />
127+
**RewiredModule.&#95;&#95;set&#95;&#95;(***name, value***)**
136128

137-
##Please note
138-
###Keys should be exactly the same like they're required in the target module
139-
So if you write`require("../../myModules/myModuleA.js")` you need to pass
140-
`{"../../myModules/myModuleA.js": myModuleAMock}`.
129+
-*{!String} name*: <br/>
130+
Name of the variable to set. The variable should be a global or defined with`var` in the top-level
131+
scope of the module.
141132

142-
###All scripts are injected at the end of the module
143-
So if there is any code in your module that is executed during`require()`, your
144-
injected variables will be undefined at this point.
133+
-*{&lowast;} value*: <br/>
134+
The value to set
145135

146-
Imagine`rewire("./myModule.js", null, {console: null});`:
136+
**RewiredModule.&#95;&#95;set&#95;&#95;(***env***)**
147137

148-
```javascript
149-
console.log("Hello");// ouch, that won't work. console is undefined at this point because of hoisting
150-
151-
// End of module ///////////////
152-
// rewire will inject here
153-
varconsole=null;
154-
```
155-
156-
###Leaks are executed at the end of the module.
157-
All variables, that are[copied by value](http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language)
158-
will not be updated anymore.
159-
160-
A good approach to solve this would be:
161-
162-
```javascript
163-
var myLeaks= {};
164-
165-
module.exports=function (someValue) {
166-
myLeaks.someValue= someValue;
167-
};
168-
```
138+
-*{!Object} env*: <br/>
139+
Takes all keys as variable names and sets the values respectively.
169140

170-
And then:```rewire("myModuleA.js", null, null, ["myLeaks"]);```
141+
**RewiredModule.&#95;&#95;get&#95;&#95;(***name***): {&lowast;}**
171142

172-
Because```myLeaks``` is defined at the end of the module, you're able to access the leak object and all leaks that
173-
are attached to it later during runtime.
143+
Returns the private variable.
174144

175-
###Call rewire.reset() after every unit test
176-
All```require()```s will now return the original module again.
177145

178146
-----------------------------------------------------------------
179147
<br />

‎lib/__get__.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"use strict";// run code in ES5 strict mode
2+
3+
/**
4+
* This function will be stringified and then injected into every rewired module.
5+
* Then you can leak private variables by calling myModule.__get__("myPrivateVar");
6+
*
7+
*@param {!String} name name of the variable to retrieve
8+
*@throws {TypeError}
9+
*@return {*}
10+
*/
11+
module.exports=function__get__(name){
12+
if(typeofname!=="string"||name==false){
13+
thrownewTypeError("__get__ expects a non-empty string");
14+
}
15+
16+
returneval(name);
17+
};

‎lib/__set__.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"use strict";// run code in ES5 strict mode
2+
3+
/**
4+
* This function will be stringified and then injected into every rewired module.
5+
* Then you can set private variables by calling myModule.__set__("myPrivateVar", newValue);
6+
*
7+
*@param {!String|!Object} varName name of the variable to set
8+
*@param {String} varValue new value
9+
*@throws {TypeError}
10+
*@return {*}
11+
*/
12+
module.exports=function__set__(varName,varValue){
13+
varkey,
14+
env,
15+
src="";
16+
17+
functioncheckExistsSrc(varName){
18+
return"if (typeof "+varName+" === 'undefined') { throw new ReferenceError('"+varName+" is not defined');} ";
19+
}
20+
21+
if(typeofvarName==="object"){
22+
env=varName;
23+
if(!env||Array.isArray(env)){
24+
thrownewTypeError("__set__ expects an object as env");
25+
}
26+
for(keyinenv){
27+
if(env.hasOwnProperty(key)){
28+
src+=checkExistsSrc(key)+key+" = env."+key+";";
29+
}
30+
}
31+
}elseif(typeofvarName==="string"){
32+
if(!varName){
33+
thrownewTypeError("__set__ expects a non-empty string as a variable name");
34+
}
35+
src=checkExistsSrc(varName)+varName+" = varValue;"
36+
}else{
37+
thrownewTypeError("__set__ expects an environment object or a non-empty string as a variable name");
38+
}
39+
40+
eval(src);
41+
};

‎lib/getImportGlobalsSrc.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"use strict";// run code in ES5 strict mode
2+
3+
/**
4+
* Declares all globals with a var and assigns the global object. Thus you're able to
5+
* override globals without changing the global object itself.
6+
*
7+
* Returns something like
8+
* "var console = console; var process = process; ..."
9+
*
10+
*@return {String}
11+
*/
12+
functiongetImportGlobalsSrc(){
13+
varkey,
14+
value,
15+
src="";
16+
17+
for(keyinglobal){
18+
if(global.hasOwnProperty(key)&&key!=="global"){
19+
value=global[key];
20+
src+="var "+key+" = global."+key+"; ";
21+
}
22+
}
23+
24+
25+
returnsrc;
26+
}
27+
28+
module.exports=getImportGlobalsSrc;

‎lib/getInjectionSrc.js

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp