1 | # Typescript Mock Imports
|
2 |
|
3 | #### Intuitive mocking for Typescript class imports.
|
4 |
|
5 | [![Build Status](https://travis-ci.org/EmandM/ts-mock-imports.svg)](https://travis-ci.org/EmandM/ts-mock-imports)
|
6 |
|
7 |
|
8 |
|
9 | - [Typescript Mock Imports](#typescript-mock-imports)
|
10 | - [Intuitive mocking for Typescript class imports.](#intuitive-mocking-for-typescript-class-imports)
|
11 | - [Installation](#installation)
|
12 | - [About](#about)
|
13 | - [Usage](#usage)
|
14 | - [API](#api)
|
15 | - [ImportMock](#importmock)
|
16 | - [MockManager (and MockStaticManager)](#mockmanager-and-mockstaticmanager)
|
17 | - [OtherManager](#othermanager)
|
18 | - [Test](#test)
|
19 | - [Typescript Tests](#typescript-tests)
|
20 | - [Unit Tests](#unit-tests)
|
21 |
|
22 |
|
23 |
|
24 | ## Installation
|
25 |
|
26 | `npm install ts-mock-imports --save-dev`
|
27 |
|
28 | ## About
|
29 |
|
30 | ts-mock-imports is useful if you want to replace classes that are exported from local files with stub versions of those classes. This allows ES6 code to be easily unit-tested without the need for a dependency injection library.
|
31 |
|
32 | ts-mock-imports is built on top of sinon.
|
33 |
|
34 | The mocked class takes all of the original class functions, and replaces them with noop functions (functions returning `undefined`).
|
35 |
|
36 | This library needs to be run on TypeScript 2.6.1 or later.
|
37 |
|
38 | ## Usage
|
39 |
|
40 | `src/foo.ts`
|
41 | ```javascript
|
42 | export class Foo {
|
43 | constructor() {
|
44 | throw new Error();
|
45 | }
|
46 | }
|
47 | ```
|
48 |
|
49 | `src/bar.ts`
|
50 | ```javascript
|
51 | import { Foo } from './foo';
|
52 |
|
53 | export class Bar {
|
54 | constructor() {
|
55 | const foo = new Foo();
|
56 | }
|
57 | }
|
58 | ```
|
59 |
|
60 | `test/bar.spec.ts`
|
61 | ```javascript
|
62 | import { ImportMock } from 'ts-mock-imports';
|
63 | import { Bar } from './Bar';
|
64 | import * as fooModule from '../src/foo';
|
65 |
|
66 | // Throws error
|
67 | const bar = new Bar();
|
68 |
|
69 | const mockManager = ImportMock.mockClass(fooModule, 'Foo');
|
70 |
|
71 | // No longer throws an error
|
72 | const bar = new Bar();
|
73 |
|
74 | // Call restore to reset to original imports
|
75 | mockManager.restore();
|
76 | ```
|
77 |
|
78 | ## API
|
79 |
|
80 | ### ImportMock
|
81 |
|
82 | **`mockClass(module: <import * as>, importName?: string ): MockManager<T>`**
|
83 |
|
84 | **module:**
|
85 |
|
86 | The module containing the class you would like to mock.
|
87 |
|
88 | Both the source file and test file need to use the same path to import the mocked module. I.e. Cannot use `'src/index'` to import into the `.spec.ts` file and then use `'src/foo'` to import into `bar.ts`. Both files need to use either `'src/foo'` or `'src/index'`.
|
89 |
|
90 | **importName:**
|
91 |
|
92 | What the class is exported as. If exported using `export default` then this parameter is not needed.
|
93 |
|
94 | Using importName:
|
95 | ```javascript
|
96 | // export class Foo
|
97 | import * as fooModule from '../src/foo';
|
98 |
|
99 | const mockManager = ImportMock.mockClass(fooModule, 'Foo');
|
100 | ```
|
101 |
|
102 | Default imports:
|
103 | ```javascript
|
104 | // export default Foo
|
105 | import * as foo from '../foo';
|
106 |
|
107 | const mockManager = ImportMock.mockClass(foo);
|
108 | ```
|
109 |
|
110 | Import mock will infer the type of `Foo` if it is the only item exported out of it's file. If more things are exported, you will need to explicitly provide types to Import mock.
|
111 |
|
112 | Explicit typing:
|
113 | ```javascript
|
114 | import * as fooModule from '../foo';
|
115 |
|
116 | const mockManager = ImportMock.mockClass<fooModule.Foo>(fooModule, 'Foo');
|
117 | ```
|
118 |
|
119 | If you wish to ensure that `Foo` is the correct name for the mocked class, give import mock the type of your module.
|
120 |
|
121 | Explicit typing with full type assurance
|
122 | ```javascript
|
123 | import * as fooModule from '../foo';
|
124 |
|
125 | const mockManager = ImportMock.mockClass<fooModule.Foo, typeof fooModule>(fooModule, 'Foo');
|
126 |
|
127 | // Will result in a TS Error as Bar is not exported by Foo
|
128 | const mockManager = ImportMock.mockClass<fooModule.Foo, typeof fooModule>(fooModule, 'Bar');
|
129 | ```
|
130 |
|
131 | ---
|
132 |
|
133 | **`mockStaticClass(module: <import * as>, importName?: string ): MockStaticManager<T>`**
|
134 |
|
135 | Takes the same arguments as `mockClass` but only replaces static functions on the original class.
|
136 |
|
137 | Static classes:
|
138 | (Only recreates static methods)
|
139 | ```javascript
|
140 | import * as fooModule from '../foo';
|
141 |
|
142 | const mockManager = ImportMock.mockStaticClass(fooModule, 'Foo');
|
143 | ```
|
144 |
|
145 | ---
|
146 |
|
147 | **`mockFunction(module: <import * as>, importName?: string, returns?: any): SinonStub`**
|
148 |
|
149 | Returns a SinonStub that is set up to return the optional argument.
|
150 |
|
151 | Call restore on the stub object to restore the original export.
|
152 |
|
153 | Function exports:
|
154 | ```javascript
|
155 | import * as fooModule from '../foo';
|
156 |
|
157 | const stub = ImportMock.mockFunction(fooModule, 'fooFunction', 'bar');
|
158 | // fooFunction will now return bar
|
159 |
|
160 | stub.restore()
|
161 | ```
|
162 |
|
163 | ---
|
164 |
|
165 | **`mockOther(module: <import * as>, importName?: string, replaceWith: any): OtherManager<T>`**
|
166 |
|
167 | `mockOther()` uses the replaceWith argument to entirely replace the original exported item.
|
168 |
|
169 | Useful for mocking out or removing variables and enums.
|
170 |
|
171 | Variable mocking:
|
172 | ```javascript
|
173 | import * as fooModule from '../foo';
|
174 |
|
175 | const mockManager = ImportMock.mockOther(fooModule, 'fooName', 'fakeName');
|
176 | // import { fooName } from './foo' now returns 'fakeName'
|
177 | ```
|
178 |
|
179 | ---
|
180 |
|
181 | ### MockManager (and MockStaticManager)
|
182 |
|
183 | **`MockManager<T>.mock(functionName: string, returns?: any): SinonStub`**
|
184 |
|
185 | This function returns a sinon stub object.
|
186 |
|
187 | **functionName:**
|
188 |
|
189 | The name of the function you would like to mock.
|
190 |
|
191 | If using MockManager, Typescript expects the functionName to match functions available on the original class.
|
192 |
|
193 | MockStaticManager allows any string.
|
194 |
|
195 | **returns:**
|
196 |
|
197 | The value returned when the mocked function is called.
|
198 |
|
199 |
|
200 | Mocking functions:
|
201 | (Returns a sinon stub)
|
202 | ```javascript
|
203 | import * as fooModule from '../foo';
|
204 |
|
205 | const fooManager = ImportMock.mockClass(fooModule, 'Foo');
|
206 |
|
207 | // Will throw a type error if bar() does not exist on Foo
|
208 | const sinonStub = fooManager.mock('bar');
|
209 | ```
|
210 |
|
211 | Mocking functions with a return object:
|
212 | ```javascript
|
213 | import * as fooModule from '../foo';
|
214 |
|
215 | const mockManager = ImportMock.mockClass(fooModule, 'Foo');
|
216 |
|
217 | const returnVal = 'Bar';
|
218 | const sinonStub = mockManager.mock('bar', returnVal);
|
219 | // new Foo().bar() now returns 'Bar'
|
220 | ```
|
221 |
|
222 | ---
|
223 |
|
224 | **`MockManager<T>.set(varName: string, replaceWith?: any): void`**
|
225 |
|
226 | Replaces a property with a given value.
|
227 |
|
228 | **varName**
|
229 |
|
230 | The name of the property you would like to mock.
|
231 |
|
232 | If using MockManager, Typescript expects the varName to match properties available on the original class.
|
233 |
|
234 | MockStaticManager allows any string.
|
235 |
|
236 | **replaceWith:**
|
237 |
|
238 | The mock value of the property.
|
239 |
|
240 |
|
241 | Mocking variable with a return object:
|
242 | ```javascript
|
243 | import * as fooModule from '../foo';
|
244 |
|
245 | const mockManager = ImportMock.mockClass(fooModule, 'Foo');
|
246 |
|
247 | const newVal = 5;
|
248 | mockManager.set('count', newVal);
|
249 | // new Foo().count now returns 5
|
250 | ```
|
251 |
|
252 | ---
|
253 |
|
254 | **`MockManager<T>.getMockInstance(): T`**
|
255 |
|
256 | Returns an instance of the mocked class.
|
257 | ```javascript
|
258 | import * as fooModule from '../foo';
|
259 |
|
260 | const mockManager = ImportMock.mockClass(fooModule, 'Foo');
|
261 |
|
262 | const sinonStub = mockManager.mock('bar', 'Bar');
|
263 | const mockFoo = mockManager.getMockInstance();
|
264 | mockFoo.bar() // returns 'Bar'
|
265 | ```
|
266 | ---
|
267 |
|
268 | **`MockManager<T>.restore()`**
|
269 |
|
270 | Restores the import back to the original class.
|
271 |
|
272 | It is important that this is called so future imports work as expected.
|
273 |
|
274 | ---
|
275 |
|
276 | ### OtherManager
|
277 |
|
278 | **`OtherManager<T>.set(replaceWith?: T): void`**
|
279 |
|
280 | Replaces an exported property with a given value.
|
281 |
|
282 | This value must match the type of the original export.
|
283 |
|
284 | **replaceWith:**
|
285 |
|
286 | The mock value of the export.
|
287 |
|
288 |
|
289 | Mocking variable with a return object:
|
290 | ```javascript
|
291 | import * as fooModule from '../foo';
|
292 |
|
293 | const mockManager = ImportMock.mockOther(fooModule, 'FooName', 'fakeName');
|
294 | // import { FooName } from './foo' imports 'fakeName'
|
295 |
|
296 | const newVal = 'newName';
|
297 | mockManager.set(newVal);
|
298 | // import { FooName } from './foo' now imports 'newName'
|
299 | ```
|
300 |
|
301 | ---
|
302 |
|
303 | **`OtherManager<T>.getValue(): T`**
|
304 |
|
305 | Returns the current mockValue
|
306 | ```javascript
|
307 | import * as fooModule from '../foo';
|
308 |
|
309 | const mockManager = ImportMock.mockOther(fooModule, 'FooName', 'fakeName');
|
310 |
|
311 | mockManager.getValue(); // returns 'fakeName'
|
312 | ```
|
313 | ---
|
314 |
|
315 | **`OtherManager<T>.restore()`**
|
316 |
|
317 | Restores the import back to the original class.
|
318 |
|
319 | It is important that this is called so future imports work as expected.
|
320 |
|
321 |
|
322 |
|
323 | ## Test
|
324 |
|
325 | ```
|
326 | npm run test
|
327 | ```
|
328 |
|
329 | ### Typescript Tests
|
330 |
|
331 | ```
|
332 | npm run dtslint
|
333 | ```
|
334 |
|
335 | ### Unit Tests
|
336 |
|
337 | ```
|
338 | npm run unit-test
|
339 | ``` |
\ | No newline at end of file |