Jest中Mock Axios无法处理默认请求头的问题求助
Got it, let's break down what's happening here and fix that error right away.
The root issue is simple: your current Jest mock only replaces axios.post, but it doesn't replicate the full structure of the axios object. When your action tries to access axios.defaults.headers.common, it hits undefined because your mock doesn't include the defaults property at all.
Solution 1: Update Your Axios Mock to Include defaults
Just extend your mock object to include the defaults structure that your code expects. This will let the action set the Authorization header without throwing an error. Here's how to adjust your mock:
import actions from "../../src/store/actions"; jest.mock("axios", () => ({ post: (_url, _body, config) => { return new Promise((resolve) => { // Don't forget to add the `user` field here too—your action tries to access it! resolve({ data: { success: { token: 'test' }, user: { id: 1, username: 'test-user' } } }); }); }, // Add the defaults structure to match axios's actual API defaults: { headers: { common: {} } } })); describe('login action', () => { it("lets the user login and triggers the login success mutator", async() => { const commit = jest.fn(); const username = 'test'; const password = 'test'; await actions.login({commit}, {username, password}); // Optional: Verify the commit was called correctly expect(commit).toHaveBeenCalledWith('LOGIN_SUCCESS', 'test', { id: 1, username: 'test-user' }); }); });
Solution 2: Use jest.spyOn for More Control (Optional)
If you want to keep the rest of axios's default behavior and only mock the post method (plus verify that the header was actually set), using jest.spyOn is a cleaner approach:
import actions from "../../src/store/actions"; import axios from "axios"; describe('login action', () => { let postSpy; beforeEach(() => { // Mock axios.post to return your test data postSpy = jest.spyOn(axios, 'post').mockResolvedValue({ data: { success: { token: 'test' }, user: { id: 1, username: 'test-user' } } }); // Reset headers between tests to avoid cross-test contamination axios.defaults.headers.common['Authorization'] = ''; // Mock localStorage if you want to verify it's used Storage.prototype.setItem = jest.fn(); }); afterEach(() => { // Restore the original axios.post method after each test postSpy.mockRestore(); }); it("logs the user in, sets the auth header, and triggers the mutator", async() => { const commit = jest.fn(); await actions.login({commit}, { username: 'test', password: 'test' }); // Verify the auth header was set correctly expect(axios.defaults.headers.common['Authorization']).toBe('Bearer test'); // Verify localStorage was updated expect(localStorage.setItem).toHaveBeenCalledWith('token', 'test'); // Verify the commit action ran expect(commit).toHaveBeenCalledWith('LOGIN_SUCCESS', 'test', { id: 1, username: 'test-user' }); }); });
Quick Notes to Avoid Other Issues
- I added the
userfield to the mock response because your action tries to assignresp.data.user—without it, you'd hit another undefined error later. - If your tests run in an environment without
localStorage(like Node.js), mockingStorage.prototype.setItemprevents errors and lets you verify that the token is being stored correctly.
内容的提问来源于stack exchange,提问作者Jamie Woods

