Skip to content

Files

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Latest commit

ce92a1d · Dec 9, 2017

History

History
70 lines (54 loc) · 2.23 KB

testing-with-mocks.md

File metadata and controls

70 lines (54 loc) · 2.23 KB

Testing with Mocks

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.

vue-loader provides a feature that allows you to inject arbitrary dependencies to a *.vue component, using 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 instance of the module with the mocks injected.

Note: You must disable esModule option in inject mode, or you will get an error.

Suppose we have a component like this:

<!-- example.vue -->
<template>
  <div class="msg">{{ msg }}</div>
</template>

<script>
// this dependency needs to be mocked
const SomeService = require('../service')

module.exports = {
  data () {
    return {
      msg: SomeService.msg
    }
  }
}
</script>

Here's how to import it with mocks:

npm install inject-loader --save-dev
// example.spec.js
const ExampleInjector = require('!!vue-loader?inject!./example.vue')

Notice that crazy require string - we are using some inline webpack loader requests here. A quick explanation:

  • !! at the start means "disable all loaders from the global config";
  • vue-loader?inject! means "use vue-loader, and pass in the ?inject query". This tells vue-loader to compile the component in dependency-injection mode.

The returned ExampleInjector is a factory function that can be called to create instances of the example.vue module:

const ExampleWithMocks = ExampleInjector({
  // mock it
  '../service': {
    msg: 'Hello from a mocked service!'
  }
})

Finally, we can test the component like usual:

it('should render', () => {
  const vm = new Vue({
    template: '<div><test></test></div>',
    components: {
      'test': ExampleWithMocks
    }
  }).$mount()
  expect(vm.$el.querySelector('.msg').textContent).to.equal('Hello from a mocked service!')
})