vue.jsvuejs2jestjsvue-test-utilsvue-testing-library

How to test Vue "Services" mounted to root, accessed via Vue.prototype


First, I'd like to explain that I have a Vue component repository that is responsible for displaying data retrieved from an http service. Rather than the component itself managing the same data retrieval per instance and spamming the client with network requests, I've managed to find a solution which allows another component to be mounted to the root directly (which I've dubbed as a "Service" due to its similarity to Angular) to manage the data those components need instead. This works great and other components can access it via Vue.prototype (via this.$TestService.value). It has some caveats but for the most part it accomplishes exactly what I needed. This may be uncommon, but those that use Vuex are using a similar methodology and I don't want to use the store paradigm.

I've made a very simple Vue JsFiddle to show this in action...

https://jsfiddle.net/spronkets/8v31tcfd/18

Now, to the point... I'm using @testing-library/vue, @vue/test-utils, and Jest to test the components and get test coverage and now I get errors anytime I run the tests due to the service not existing on the Vue.prototype during the test execution. I don't want to mock out the functionality of the "Service" layer, so does anyone have a solution to test these root-mounted components? I've tried manually exporting the services (unmounted and mounted) and including them in the mock section as well as importing the files directly into the test files but the "Service" is always undefined when the component is trying to retrieve the value and ONLY during test execution...

I've also created a simple repository modelled after the Vue component repository I am working with below...

https://github.com/kcrossman/VueServiceExample

To get started, clone the repo and follow the README.md included in the repo. Thanks!


Solution

  • Update: For those that might be referring to this in the future, Vue Plugins might be a better solution for this kind of functionality.


    I stumbled along this issue in GitHub and that led me to the fix I made below:

    https://github.com/testing-library/vue-testing-library/issues/113

    Specifically, this comment by user nikravi:

    ok, I found the fix. The trick was to add
    
    import Vue from "vue";
    import Vuetify from "vuetify";
    Vue.use(Vuetify);
    
    and then the render() works without warnings.
    

    After I manually imported Vue and set Vue.prototype.$TestService = TestService directly in the unit test, it got passed that error. Personally, I think this is pretty silly, but it worked.

    After this worked, I also found that you can access the Vue instance directly within the render callback (from @testing-library/vue), so I finished on this code instead of importing Vue:

    render(TestComponent, {}, vue => {
        vue.prototype.$TestService = TestService;
    });
    

    I've included all the commits to solve my issue in the repo I posted previously:

    https://github.com/kcrossman/VueServiceExample

    Some of the tests were malformed but once I made those changes, the tests started to work and I updated some other files to be a bit nicer for people to refer to.