|
| 1 | +# Testing with Mocks |
| 2 | + |
| 3 | +> This feature requires `vue-loader@^7.3.0`. |
| 4 | +
|
| 5 | +In a real world application, our components most likely have external dependencies. When writing unit tests for components, it would be ideal if we can mock these external dependencies so that our tests only rely the behavior of the component being tested. |
| 6 | + |
| 7 | +`vue-loader` provides a feature that allows you to inject arbitrary dependencies to a `*.vue` component, using [inject-loader](https://github.com/plasticine/inject-loader). The general idea is that instead of directly importing the component module, we use `inject-loader` to create a "module factory" function for that module. When this function gets called with an object of mocks, it returns an instances of the module with the mocks injected. |
| 8 | + |
| 9 | +Suppose we have a component like this: |
| 10 | + |
| 11 | +``` html |
| 12 | +<!-- example.vue --> |
| 13 | +<template> |
| 14 | + <div class="msg">{{ msg }}&l
10000
t;/div> |
| 15 | +</template> |
| 16 | + |
| 17 | +<script> |
| 18 | +// this dependency needs to be mocked |
| 19 | +import SomeService from '../service' |
| 20 | +
|
| 21 | +export default { |
| 22 | + data () { |
| 23 | + return { |
| 24 | + msg: SomeService.msg |
| 25 | + } |
| 26 | + } |
| 27 | +} |
| 28 | +</script> |
| 29 | +``` |
| 30 | + |
| 31 | +Here's how to import it with mocks: |
| 32 | + |
| 33 | +``` bash |
| 34 | +npm install inject-loader --save-dev |
| 35 | +``` |
| 36 | + |
| 37 | +``` js |
| 38 | +// example.spec.js |
| 39 | +const ExampleInjector = require('!!vue?inject!./example.vue') |
| 40 | +``` |
| 41 | + |
| 42 | +Notice that crazy require string - we are using some inline [webpack loader requests](https://webpack.github.io/docs/loaders.html) here. A quick explanation: |
| 43 | + |
| 44 | +- `!!` at the start means "disable all loaders from the global config"; |
| 45 | +- `vue?inject!` means "use the `vue` loader, and pass in the `?inject` query". This tells `vue-loader` to compile the component in dependency-injection mode. |
| 46 | + |
| 47 | +The returned `ExampleInjector` is a factory function that can be called to create instances of the `example.vue` module: |
| 48 | + |
| 49 | +``` js |
| 50 | +const ExampleWithMocks = ExampleInjector({ |
| 51 | + // mock it |
| 52 | + '../service': { |
| 53 | + msg: 'Hello from a mocked service!' |
| 54 | + } |
| 55 | +}) |
| 56 | +``` |
| 57 | + |
| 58 | +Finally, we can test the component like usual: |
| 59 | + |
| 60 | +``` js |
| 61 | +it('should render', () => { |
| 62 | + const vm = new Vue({ |
| 63 | + template: '<div><test></test></div>', |
| 64 | + components: { |
| 65 | + 'test': ExampleWithMocks |
| 66 | + } |
| 67 | + }).$mount() |
| 68 | + expect(vm.$el.querySelector('.msg').textContent).toBe('Hello from a mocked service!') |
| 69 | +}) |
| 70 | +``` |
0 commit comments