Reputation: 9692
I'm new to Cypress component testing, but I was able to set it up easily for my Vue project. I'm currently investigating if we should replace Jest with Cypress to test our Vue components and I love it so far, there is only one major feature I'm still missing: mocking modules. I first tried with cy.stub()
, but it simply didn't work which could make sense since I'm not trying to mock the actual module in Node.js, but the module imported within Webpack.
To solve the issue, I tried to use rewiremock which is able to mock Webpack modules, but I'm getting an error when running the test:
I forked the examples from Cypress and set up Rewiremock in this commit. Not sure what I'm doing wrong to be honest.
I really need to find a way to solve it otherwise, we would simply stop considering Cypress and just stick to Jest. If using Rewiremock is not the way, how am I suppose to achieve this? Any help would be greatly appreciated.
Upvotes: 2
Views: 2067
Reputation: 2226
We solved this by using webpack aliases in the Cypress webpack config to intercept the node_module dependency.
So something like...
// cypress/plugins/index.js
const path = require("path");
const { startDevServer } = require('@cypress/webpack-dev-server');
// your project's base webpack config
const webpackConfig = require('@vue/cli-service/webpack.config');
module.exports = (on, config) => {
on("dev-server:start", (options) => {
webpackConfig.resolve.alias["your-module"] = path.resolve(__dirname, "path/to/your-module-mock.js");
return startDevServer({
options,
webpackConfig,
})
});
}
// path/to/your-module-mock.js
let yourMock;
export function setupMockModule(...) {
yourMock = {
...
};
}
export default yourMock;
// your-test.spec.js
import { setupMock } from ".../your-module-mock.js"
describe("...", () => {
before(() => {
setupMock(...);
});
it("...", () => {
...
});
});
Upvotes: 0
Reputation: 23463
If you are able to adjust the Vue component to make it more testable, the function can be mocked as a component property.
Webpack
When vue-loader processes HelloWorld.vue
, it evaluates getColorOfFruits()
and sets the data property, so to mock the function here, you need a webpack re-writer like rewiremock.
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
colorOfFruits: getColorOfFruits(), // during compile time
};
},
...
Vue created hook
If you initiialize colorOfFruits
in the created()
hook, you can stub the getColorOfFruits
function after import but prior to mounting.
HelloWorld.vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>{{ colorOfFruits.apple }}</h2>
<p>
...
</template>
<script lang="ts">
import { getColorOfFruits } from "@/helpers/fruit.js";
export default {
name: "HelloWorld",
getColorOfFruits, // add this function to the component for mocking
props: {
msg: String,
},
data() {
return {
colorOfFruits: {} // initialized empty here
};
},
created() {
this.colorOfFruits = this.$options.colorOfFruits; // reference function saved above
}
});
</script>
HelloWorld.spec.js
import { mount } from "@cypress/vue";
import HelloWorld from "./HelloWorld.vue";
it("mocks an apple", () => {
const getMockFruits = () => {
return {
apple: "green",
orange: "purple",
}
}
HelloWorld.getColorOfFruits = getMockFruits;
mount(HelloWorld, { // created() hook called as part of mount()
propsData: {
msg: "Hello Cypress!",
},
});
cy.get("h1").contains("Hello Cypress!");
cy.get("h2").contains('green')
});
Upvotes: 2