无法读取未定义的 属性 'endsWith' - Redux 工具包测试
Cannot read property 'endsWith' of undefined - Redux Toolkit testing
我在使用 React 测试库测试切片时遇到问题。我是运行下面的简单测试:
import reducer from "states/slices";
test("should return the initial state", () => {
expect(reducer(undefined, {})).toEqual({
loading: true,
libraries: [],
books: [],
error: {
error: false,
variant: "error",
message: "",
},
});
});
被测切片如下:
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { getLibraries, getBooks } from "api";
const initialState = {
loading: true,
libraries: [],
books: [],
error: {
error: false,
variant: "error",
message: "",
},
};
export const fetchLibraries = createAsyncThunk("books/libraries", async () => {
const res = await getLibraries();
return res.data;
});
export const fetchBooks = createAsyncThunk(
"books/books",
async ({ title, libraryId, page }) => {
const res = await getBooks(title, libraryId, page);
return res.data;
}
);
const booksSlice = createSlice({
name: "books",
initialState,
reducers: {
unsetError: (state) => {
state.error = { error: false, variant: "error", message: "" };
},
},
extraReducers: (builder) => {
builder
.addCase(fetchLibraries.fulfilled, (state, action) => {
state.loading = false;
state.libraries = action.payload;
})
.addCase(fetchBooks.fulfilled, (state, action) => {
state.loading = false;
state.books = action.payload;
})
// .addCase(fetchBooks.pending, (state, action) => {
// state.loading = true;
// state.error = { error: false, variant: "error", message: "" };
// })
// .addCase(fetchLibraries.pending, (state, action) => {
// state.loading = true;
// state.error = { error: false, variant: "error", message: "" };
// })
// .addCase(fetchBooks.rejected, (state, action) => {
// state.loading = false;
// state.error.error = true;
// state.error.variant = "error";
// state.error.message =
// "Error. Try again.";
// })
// .addCase(fetchLibraries.rejected, (state, action) => {
// state.loading = false;
// state.error.error = true;
// state.error.variant = "error";
// state.error.message =
// "Error. Try again.";
// });
.addMatcher(
(action) => action.type.endsWith("/pending"),
(state, action) => {
state.loading = true;
state.error = { error: false, variant: "error", message: "" };
}
)
.addMatcher(
(action) => action.type.endsWith("/rejected"),
(state, action) => {
state.loading = false;
state.error.error = true;
state.error.variant = "error";
state.error.message =
"Error. Try again.";
}
);
},
});
const { actions, reducer } = booksSlice;
export const { unsetError } = actions;
export default reducer;
当 运行 切片中包含 addMatcher
的测试时,我将返回 TypeError: Cannot read property 'endsWith' of undefined
。如果我将它们替换为 addCase
s(注释的),测试将按预期进行。
相反,如果我正常启动应用程序,则在任何一种情况下一切正常。
为什么会这样?我错误地定义了匹配器?
在您的测试用例中,您使用 {}
作为一个动作。因此,当您检查匹配器 action.type.endsWith()
时,未定义 action.type
。
如果您在匹配器中使用 action.type?.endsWith
,您或许可以解决此问题。
我在使用 React 测试库测试切片时遇到问题。我是运行下面的简单测试:
import reducer from "states/slices";
test("should return the initial state", () => {
expect(reducer(undefined, {})).toEqual({
loading: true,
libraries: [],
books: [],
error: {
error: false,
variant: "error",
message: "",
},
});
});
被测切片如下:
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { getLibraries, getBooks } from "api";
const initialState = {
loading: true,
libraries: [],
books: [],
error: {
error: false,
variant: "error",
message: "",
},
};
export const fetchLibraries = createAsyncThunk("books/libraries", async () => {
const res = await getLibraries();
return res.data;
});
export const fetchBooks = createAsyncThunk(
"books/books",
async ({ title, libraryId, page }) => {
const res = await getBooks(title, libraryId, page);
return res.data;
}
);
const booksSlice = createSlice({
name: "books",
initialState,
reducers: {
unsetError: (state) => {
state.error = { error: false, variant: "error", message: "" };
},
},
extraReducers: (builder) => {
builder
.addCase(fetchLibraries.fulfilled, (state, action) => {
state.loading = false;
state.libraries = action.payload;
})
.addCase(fetchBooks.fulfilled, (state, action) => {
state.loading = false;
state.books = action.payload;
})
// .addCase(fetchBooks.pending, (state, action) => {
// state.loading = true;
// state.error = { error: false, variant: "error", message: "" };
// })
// .addCase(fetchLibraries.pending, (state, action) => {
// state.loading = true;
// state.error = { error: false, variant: "error", message: "" };
// })
// .addCase(fetchBooks.rejected, (state, action) => {
// state.loading = false;
// state.error.error = true;
// state.error.variant = "error";
// state.error.message =
// "Error. Try again.";
// })
// .addCase(fetchLibraries.rejected, (state, action) => {
// state.loading = false;
// state.error.error = true;
// state.error.variant = "error";
// state.error.message =
// "Error. Try again.";
// });
.addMatcher(
(action) => action.type.endsWith("/pending"),
(state, action) => {
state.loading = true;
state.error = { error: false, variant: "error", message: "" };
}
)
.addMatcher(
(action) => action.type.endsWith("/rejected"),
(state, action) => {
state.loading = false;
state.error.error = true;
state.error.variant = "error";
state.error.message =
"Error. Try again.";
}
);
},
});
const { actions, reducer } = booksSlice;
export const { unsetError } = actions;
export default reducer;
当 运行 切片中包含 addMatcher
的测试时,我将返回 TypeError: Cannot read property 'endsWith' of undefined
。如果我将它们替换为 addCase
s(注释的),测试将按预期进行。
相反,如果我正常启动应用程序,则在任何一种情况下一切正常。
为什么会这样?我错误地定义了匹配器?
在您的测试用例中,您使用 {}
作为一个动作。因此,当您检查匹配器 action.type.endsWith()
时,未定义 action.type
。
如果您在匹配器中使用 action.type?.endsWith
,您或许可以解决此问题。