У меня есть проект React/Typescript, в котором я использую MobX-State-Tree для управления состоянием. В одном из моих тестов (с использованием библиотеки тестирования Vitest + React) я имитировал функцию, определенную в одном из хранилищ в дереве состояний, поэтому я могу проверить ее вызов (она должна вызываться в useEffect при монтировании). Но тест работает неправильно.
Образец магазина:
const SampleStore = types.model({
...
}).actions(self => ({
sample_action: flow(function* (param: string) {
//sample async action call with yield
})
})
...
export const sample_store = SampleStore.create()
Компонент:
// all imports
export const SampleComponentPage = () => {
....
useEffect(() => {
// the action from the store gets called here
sample_store.sample_action(arg)
}, [])
return (
...
)
})
Тестовый файл:
...
describe('Sample component page', () => {
it('sample test case', async () => {
const mock_action = vi.fn()
const initialStore = SampleStore.create({
sample_action: mock_action
})
render(
<StoreContextProvider value = {initialStore}>
<SampleComponentPage />
</StoreContextProvider>
)
...
waitFor(() => expect(mock_action).toHaveBeenCalled())
...
})
})
Оператор waitFor возвращает ложноположительный тест — тест проходит независимо, например, с toHaveBeenCalledTimes(10), даже если его нужно было вызвать только один раз.
Без waitFor, то есть вызова expect(mock_action).toHaveBeenCalled(), возвращается эта ошибка:
AssertionError: expected "spy" to be called once, but got 0 times
Я пробовал использовать vi.spyOn(initialStore, 'sample_action') для указания действия магазина на фиктивную функцию, но это возвращает ошибку, связанную с MST:
Error: [mobx-state-tree] Cannot modify 'AnonymousModel@/...', the object is protected and can only be modified by using an action.
❯ fail node_modules/mobx-state-tree/dist/mobx-state-tree.js:3901:12
Какое лучшее решение для этого, пожалуйста? Я хочу проверить, вызывается ли действие магазина.
попробуйте обернуть ваш рендер, например await act( async () => { render(<MyComponent/>, container) });
@LinDu фактическая функция — это действие, определенное в хранилище дерева состояний MobX, и оно вызывается в useEffect() компонента, где я оставил комментарий. mock_action — моя попытка издеваться над функцией, чтобы проверить, действительно ли она вызывается
@EdgarOrtega не уверен, что вы имели в виду с помощью container, но использование await и async для рендеринга не работает
@LinDu Я обновил вопрос для большей ясности, спасибо.





Я столкнулся с аналогичной проблемой при переносе нашего набора тестов с jest на vitest. Модель по умолчанию защищена MobX-State-Tree и не может быть изменена напрямую, как указано в ошибке. Однако вы можете отключить это в своем тесте, позвонив unprotect(initialStore) перед vi.spyOn.
import { unprotect } from "mobx-state-tree";
it('sample test case', async () => {
const initialStore = SampleStore.create(...);
unprotect(initialStore);
const spy = vi.spyOn(initialStore, 'submit_answer')
expect(spy).toHaveBeenCalled();
});
Ознакомьтесь с документацией MobX-State-Tree Unprotect API.
Это работает, спасибо, но я надеялся, что есть способ не снимать защиту магазина😬 Есть еще какие-нибудь предложения?
Как вы назвали
mock_action?