如何在Vitest中验证Quasar Q-btn组件:to属性触发的router.push行为?
Hey there! The issue here is that Quasar's Q-btn doesn't directly call the router.push() from the useRouter() hook you mocked—it uses Quasar's own integrated routing utilities under the hood, specifically relying on either $q.router or the global $router instance provided by Vue Router in the Quasar context. Your current mock only covers the useRouter() hook, but the button isn't using that directly.
Here's how to fix your test properly:
1. Mock the Quasar Router Instance
Since Q-btn leverages Quasar's $q.router for navigation when using the :to prop, you need to inject a mocked version of this into your component's mounting context:
import { mount } from '@vue/test-utils'; import QBtn from 'quasar/src/components/btn/QBtn.vue'; import vi from 'vitest'; test('click on button navigates to someView', async () => { // Create a mock push function const mockPush = vi.fn(); // Mount the QBtn with mocked Quasar router and Vue Router instances const wrapper = mount(QBtn, { global: { provide: { // Mock Quasar's $q.router which Q-btn uses for navigation $q: { router: { push: mockPush } } }, // Also mock global $router as a fallback (some cases might use this) mocks: { $router: { push: mockPush } } }, props: { to: { name: 'someView' } } }); // Trigger the button click await wrapper.trigger('click'); // Verify the push was called correctly expect(mockPush).toHaveBeenCalledOnce(); expect(mockPush).toHaveBeenCalledWith({ name: 'someView' }); });
2. Use Quasar's Official Testing Utilities (Recommended)
If you're using Quasar's official testing extension (@quasar/quasar-app-extension-testing-unit-vitest), use mountQuasar to automatically set up the Quasar environment, which simplifies mocking routing:
import { mountQuasar } from '@quasar/quasar-app-extension-testing-unit-vitest'; import QBtn from 'quasar/src/components/btn/QBtn.vue'; import vi from 'vitest'; test('click on button navigates to someView', async () => { const mockPush = vi.fn(); // Mock the router instance returned by useRouter vi.mock('vue-router', () => ({ useRouter: vi.fn(() => ({ push: mockPush })) })); // Mount with Quasar's helper const wrapper = await mountQuasar(QBtn, { props: { to: { name: 'someView' } } }); await wrapper.trigger('click'); expect(mockPush).toHaveBeenCalledOnce(); expect(mockPush).toHaveBeenCalledWith({ name: 'someView' }); });
Why Your Original Test Failed
Quasar components are designed to work within the Quasar ecosystem. When you use :to on Q-btn, it doesn't invoke the useRouter() hook directly in your code—it uses Quasar's internal references to the router (either $q.router or the global $router). Your initial mock only covered the useRouter() export, which the button doesn't rely on for its navigation logic.
内容的提问来源于stack exchange,提问作者G.Brown

