用笑话替换默认导出对象
Replace default export object with jest
我想在每个测试中都使用新的 Vuex 商店,所以我想用测试商店替换默认商店。原因是我的路由器正在使用商店 getter 检查是否允许用户访问特定路由。
问题是它总是使用默认存储,测试组件不使用它。我试过模拟 @\store
,但看起来我遗漏了什么。
@\store\index.ts
import {createStore, Store} from 'vuex'
import {State} from '@vue/runtime-core'
import auth from "@/store/modules/auth";
export const createNewStore = (): Store<State> => (createStore({
modules: {
auth,
},
}))
export default createNewStore()
@\router\index.ts
import {createMemoryHistory, createRouter, createWebHistory, Router, RouteRecordRaw} from 'vue-router'
import store from '@/store';
const routes: Array<RouteRecordRaw> = [ ... ]
export const createNewRouter = (): Router => {
const isServer = Boolean(typeof module !== 'undefined' && module.exports)
const router = createRouter({
history: isServer ? createMemoryHistory() : createWebHistory(process.env.BASE_URL),
routes
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => !record.meta.doesntRequiresAuth) && !store.getters['auth/isAuthenticated']) {
next({name: 'login'})
} else {
next()
}
})
return router
}
export default createNewRouter()
当前的实现如下所示:
@\views\__tests__\Login.spec.ts
import {render, screen} from '@testing-library/vue';
import AppComponent from '../../App.vue';
import userEvent from "@testing-library/user-event";
import {createNewRouter} from "@/router";
const {createNewStore} = jest.requireActual('@/store');
import {Router} from "vue-router";
describe('Login.vue', () => {
let router : Router
const renderComponentWithDependencies = async () => {
const mockStore = createNewStore();
jest.doMock('@/store', () => ({
__esModule: true,
default: mockStore,
}));
router = createNewRouter();
await router.push('/')
render(AppComponent, {
global: {
plugins: [router, mockStore],
}
})
}
beforeEach(async () => {
await renderComponentWithDependencies()
fetchMock.resetMocks();
});
it('User logs with correct username and pin', async () => {
const username = 'Pavel'
const pin = 'test'
fetchMock.mockResponseOnce(JSON.stringify({}));
fetchMock.mockResponseOnce(JSON.stringify({token: "123"}));
await screen.findByLabelText("Имя пользователя")
userEvent.type(screen.getByLabelText("Имя пользователя"), username)
await userEvent.click(screen.getByText('Запросить пин'))
userEvent.type(await screen.findByLabelText('Пин код'), pin)
await userEvent.click(screen.getByText('Войти'))
await router.isReady()
await screen.findByText('You are on home page')
})
})
事实证明有更好的解决方案我不知道,它不需要模拟 - 使用 jest.resetModules()
:
import {render, screen} from '@testing-library/vue';
import AppComponent from '../../App.vue';
import userEvent from "@testing-library/user-event";
import router from "@/router";
import store from '@/store';
describe('Login.vue', () => {
const renderComponentWithDependencies = async () => {
await router.push('/')
// We use App component instead of Login to test routing to homepage at the end of the login
render(AppComponent, {
global: {
plugins: [router, store],
}
})
}
beforeEach(async () => {
await renderComponentWithDependencies()
fetchMock.resetMocks();
jest.resetModules();
});
it('User logs with correct username and pin', async () => {
const username = 'Pavel'
const pin = 'test'
fetchMock.mockResponseOnce(JSON.stringify({}));
fetchMock.mockResponseOnce(JSON.stringify({token: "123"}));
await screen.findByLabelText("Имя пользователя")
userEvent.type(screen.getByLabelText("Имя пользователя"), username)
await userEvent.click(screen.getByText('Запросить пин'))
userEvent.type(await screen.findByLabelText('Пин код'), pin)
await userEvent.click(screen.getByText('Войти'))
await router.isReady()
await screen.findByText('You are on home page')
})
})
我想在每个测试中都使用新的 Vuex 商店,所以我想用测试商店替换默认商店。原因是我的路由器正在使用商店 getter 检查是否允许用户访问特定路由。
问题是它总是使用默认存储,测试组件不使用它。我试过模拟 @\store
,但看起来我遗漏了什么。
@\store\index.ts
import {createStore, Store} from 'vuex'
import {State} from '@vue/runtime-core'
import auth from "@/store/modules/auth";
export const createNewStore = (): Store<State> => (createStore({
modules: {
auth,
},
}))
export default createNewStore()
@\router\index.ts
import {createMemoryHistory, createRouter, createWebHistory, Router, RouteRecordRaw} from 'vue-router'
import store from '@/store';
const routes: Array<RouteRecordRaw> = [ ... ]
export const createNewRouter = (): Router => {
const isServer = Boolean(typeof module !== 'undefined' && module.exports)
const router = createRouter({
history: isServer ? createMemoryHistory() : createWebHistory(process.env.BASE_URL),
routes
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => !record.meta.doesntRequiresAuth) && !store.getters['auth/isAuthenticated']) {
next({name: 'login'})
} else {
next()
}
})
return router
}
export default createNewRouter()
当前的实现如下所示:
@\views\__tests__\Login.spec.ts
import {render, screen} from '@testing-library/vue';
import AppComponent from '../../App.vue';
import userEvent from "@testing-library/user-event";
import {createNewRouter} from "@/router";
const {createNewStore} = jest.requireActual('@/store');
import {Router} from "vue-router";
describe('Login.vue', () => {
let router : Router
const renderComponentWithDependencies = async () => {
const mockStore = createNewStore();
jest.doMock('@/store', () => ({
__esModule: true,
default: mockStore,
}));
router = createNewRouter();
await router.push('/')
render(AppComponent, {
global: {
plugins: [router, mockStore],
}
})
}
beforeEach(async () => {
await renderComponentWithDependencies()
fetchMock.resetMocks();
});
it('User logs with correct username and pin', async () => {
const username = 'Pavel'
const pin = 'test'
fetchMock.mockResponseOnce(JSON.stringify({}));
fetchMock.mockResponseOnce(JSON.stringify({token: "123"}));
await screen.findByLabelText("Имя пользователя")
userEvent.type(screen.getByLabelText("Имя пользователя"), username)
await userEvent.click(screen.getByText('Запросить пин'))
userEvent.type(await screen.findByLabelText('Пин код'), pin)
await userEvent.click(screen.getByText('Войти'))
await router.isReady()
await screen.findByText('You are on home page')
})
})
事实证明有更好的解决方案我不知道,它不需要模拟 - 使用 jest.resetModules()
:
import {render, screen} from '@testing-library/vue';
import AppComponent from '../../App.vue';
import userEvent from "@testing-library/user-event";
import router from "@/router";
import store from '@/store';
describe('Login.vue', () => {
const renderComponentWithDependencies = async () => {
await router.push('/')
// We use App component instead of Login to test routing to homepage at the end of the login
render(AppComponent, {
global: {
plugins: [router, store],
}
})
}
beforeEach(async () => {
await renderComponentWithDependencies()
fetchMock.resetMocks();
jest.resetModules();
});
it('User logs with correct username and pin', async () => {
const username = 'Pavel'
const pin = 'test'
fetchMock.mockResponseOnce(JSON.stringify({}));
fetchMock.mockResponseOnce(JSON.stringify({token: "123"}));
await screen.findByLabelText("Имя пользователя")
userEvent.type(screen.getByLabelText("Имя пользователя"), username)
await userEvent.click(screen.getByText('Запросить пин'))
userEvent.type(await screen.findByLabelText('Пин код'), pin)
await userEvent.click(screen.getByText('Войти'))
await router.isReady()
await screen.findByText('You are on home page')
})
})