Ben Claar
Ben Claar

Reputation: 3415

Karma/Jasmine/Vue/Sinon unit tests - mock a Vue child component?

I would like to test my Parent component independently of its Child components:

Parent.vue

<template><div>
    Hello World
    <child></child>
</div></template>

<script>
    import Child from './Child.vue'

    export default {
        components: {Child}
    }
</script>

Child.vue

<template><div>Child</div></template>

<script>
    export default {}
</script>

parent.spec.js

import Vue from 'vue'
import Parent from '../components/Parent.vue'

describe('Parent', () => {

    it('should show mocked child', function () {
        const Child = {
            template: '<div>Mocked</div>'
        }

        const vm = new Vue({
            template: '<parent></parent>',
            components: {Parent, Child},
        }).$mount();

        expect(vm.$el.textContent).not.toContain('Child')
        expect(vm.$el.textContent).toContain('Mocked')
    });
});

Failing result

PhantomJS 2.1.1 (Mac OS X 0.0.0) Parent should show mocked child FAILED
    Expected '
        Hello World
        Child' not to contain 'Child'.
    webpack:///resources/assets/js/tests/parent.spec.js:16:49 <- tests/parent.spec.js:9880:49
    Expected '
        Hello World
        Child' to contain 'Mocked'.
    webpack:///resources/assets/js/tests/parent.spec.js:17:45 <- tests/parent.spec.js:9881:45

Upvotes: 0

Views: 1279

Answers (1)

Ben Claar
Ben Claar

Reputation: 3415

Use shallow rendering to test a Vue component independently.

There are several Vue helper libraries with shallow rendering -- here's an example with vue-init (https://github.com/wrseward/vue-unit#shallow):

import { mount, shallow, beforeEachHooks, afterEachHooks } from 'vue-unit'
import Parent from '../components/Parent.vue'

describe('Parent', () => {

    beforeEach(beforeEachHooks)

    it('should show mocked child', function () {
        const vm = shallow(Parent)

        expect(vm.$el.textContent).toContain('Hello World')
        expect(vm.$el.textContent).not.toContain('Child')
    });

    afterEach(afterEachHooks)
});

If you need the ability to actually replace the component with a mock as in my original question, see the vuenit library's stubComponents method, which I was also able to get working -- the critical line is const vm = mount(Parent, {stubComponents: '<div>Mocked</div>'}).

Interestingly, the Vue.js unit testing documentation claims that they may one day add such test helpers to core:

We are planning to work on a collection of common test helpers that makes it even simpler to render components with different constraints (e.g. shallow rendering that ignores child components) and assert their output.`

Upvotes: 1

Related Questions