forked from dwyl/aws-sdk-mock
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
162 lines (144 loc) · 4.43 KB
/
index.js
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
'use strict';
/**
* Helpers to mock the AWS SDK Services using sinon.js under the hood
* Export two functions:
* - mock
* - restore
*
* Mocking is done in two steps:
* - mock of the constructor for the service on AWS
* - mock of the method on the service
**/
var sinon = require('sinon');
var traverse = require('traverse');
var _AWS = require('aws-sdk');
var AWS = {};
var services = {};
/**
* Sets the aws-sdk to be mocked.
*/
AWS.setSDK = function(path) {
_AWS = require(path);
};
/**
* Stubs the service and registers the method that needs to be mocked.
*/
AWS.mock = function(service, method, replace) {
// If the service does not exist yet, we need to create and stub it.
if (!services[service]) {
services[service] = {};
/**
* Save the real constructor so we can invoke it later on.
* Uses traverse for easy access to nested services (dot-separated)
*/
services[service].Constructor = traverse(_AWS).get(service.split('.'));
services[service].methodMocks = {};
services[service].invoked = false;
mockService(service);
}
// Register the method to be mocked out.
if(!services[service].methodMocks[method]) {
services[service].methodMocks[method] = { replace: replace };
// If the constructor was already invoked, we need to mock the method here.
if(services[service].invoked) {
mockServiceMethod(service, services[service].client, method, replace);
}
}
return services[service].methodMocks[method];
}
/**
* Stub the constructor for the service on AWS.
* E.g. calls of new AWS.SNS() are replaced.
*/
function mockService(service) {
var nestedServices = service.split('.');
var method = nestedServices.pop();
var object = traverse(_AWS).get(nestedServices);
var serviceStub = sinon.stub(object, method, function(args) {
services[service].invoked = true;
/**
* Create an instance of the service by calling the real constructor
* we stored before. E.g. var client = new AWS.SNS()
* This is necessary in order to mock methods on the service.
*/
var client = new services[service].Constructor(args);
services[service].client = client;
// Once this has been triggered we can mock out all the registered methods.
for (var key in services[service].methodMocks) {
mockServiceMethod(service, client, key, services[service].methodMocks[key].replace);
};
return client;
});
services[service].stub = serviceStub;
};
/**
* Stubs the method on a service.
*
* All AWS service methods take two argument:
* - params: an object.
* - callback: of the form 'function(err, data) {}'.
*/
function mockServiceMethod(service, client, method, replace) {
services[service].methodMocks[method].stub = sinon.stub(client, method, function() {
// If the value of 'replace' is a function we call it with the arguments.
if(typeof(replace) === 'function') {
return replace.apply(replace, arguments);
}
// Else we call the callback with the value of 'replace'.
else {
var callback = arguments[arguments.length - 1];
return callback(null, replace);
}
});
}
/**
* Restores the mocks for just one method on a service, the entire service, or all mocks.
*
* When no parameters are passed, everything will be reset.
* When only the service is passed, that specific service will be reset.
* When a service and method are passed, only that method will be reset.
*/
AWS.restore = function(service, method) {
if(!service) {
restoreAllServices();
} else {
if (method) {
restoreMethod(service, method);
} else {
restoreService(service);
}
};
}
/**
* Restores all mocked service and their corresponding methods.
*/
function restoreAllServices() {
for (var service in services) {
restoreService(service);
}
}
/**
* Restores a single mocked service and its corresponding methods.
*/
function restoreService(service) {
restoreAllMethods(service);
services[service].stub.restore();
delete services[service];
}
/**
* Restores all mocked methods on a service.
*/
function restoreAllMethods(service) {
for (var method in services[service].methodMocks) {
restoreMethod(service, method);
}
}
/**
* Restores a single mocked method on a service.
*/
function restoreMethod(service, method) {
services[service].methodMocks[method]
services[service].methodMocks[method].stub.restore();
delete services[service].methodMocks[method];
}
module.exports = AWS;