Not all computations get settled when testing a complex effector application with fork and mocked handlers

huangapple go评论58阅读模式
英文:

Not all computations get settled when testing a complex effector application with fork and mocked handlers

问题

我正在努力测试下面的效应程序:

// === module1.js ===
export const $storeA = createStore({testA: false});
export const $storeB = createStore({testB: false});

export const fetchDataFx = createEffect(() => someAsyncFnUsingAxios());

// === module2.js ===
$storeB.on(fetchDataFx.doneData, (_, {data}) => ({testB: data}));

// === module3.js ===
export const $storeC = combine($storeA, $storeB).map(([storeA, storeB]) => storeA && storeB);

// === module3.test.js ===
import {fetchDataFx, $storeA} from 'module1';
import {$storeC} from 'module3';

describe('some test', () => {
  test('should return true when fetched data is true', async () => {
    const scope = fork({
      handlers: [
        [fetchDataFx, () => Promise.resolve({data: true})],
      ],
      values: [
        [$storeA, {testA: true}],
        // not setting $storeB on purpose, as we want to test whether the fetched data is stored and calculated
      ],
    });

    await allSettled(fetchDataFx, {scope});

    expect(scope.getState($storeC)).toBe(true); // FAILS!
  });
});

模拟的处理程序被调用了,但是

$storeB.on(fetchDataFx.doneData, (_, {data}) => ({testB: data}));

没有被触发!

有什么想法吗?

我尝试了遵循 https://dev.to/effector/the-best-part-of-effector-4c27 上的说明。

我还尝试用普通的存储替换派生存储并使用 sample 进行更新:

export const $storeC = createStore(false);

sample({
  source: [$storeA, $storeB],
  fn: ([storeA, storeB]) => storeA && storeB,
  target: $storeC
});

但这也没有起作用。

英文:

I'm struggling to get the below effector application tested:

// === module1.js ===
export const $storeA = createStore({testA: false});
export const $storeB = createStore({testB: false});

export const fetchDataFx = createEffect(() => someAsyncFnUsingAxios());

// === module2.js ===
$storeB.on(fetchDataFx.doneData, (_, {data}) => ({testB: data}));

// === module3.js ===
export const $storeC = combine($storeA, $storeB).map(([storeA, storeB]) => storeA && storeB);

// === module3.test.js ===
import {fetchDataFx, $storeA} from 'module1';
import {$storeC} from 'module3';

describe('some test', () => {
  test('should return true when fetched data is true', async () => {
    const scope = fork({
      handlers: [
        [fetchDataFx, () => Promise.resolve({data: true})],
      ],
      values: [
        [$storeA, {testA: true}],
        // not setting $storeB on purpose, as we want to test whether the fetched data is stored and calculated
      ],
    });

    await allSettled(fetchDataFx, {scope});

    expect(scope.getState($storeC)).toBe(true); // FAILS!
  });
});

The mocked handler gets called, but

$storeB.on(fetchDataFx.doneData, (_, {data}) => ({testB: data}));

does not get triggered!

Any ideas?

I've tried following the instructions from https://dev.to/effector/the-best-part-of-effector-4c27

I've also tried replacing the derived store with a regular one and use sample to make it update:

export const $storeC = createStore(false);

sample({
  source: [$storeA, $storeB],
  fn: ([storeA, storeB]) => storeA && storeB,
  target: $storeC
});

but it also didn't work.

答案1

得分: 0

问题原来出在导入上。测试模块必须导入任何定义了一些效应计算的模块,以便 effector 能够意识到它们。现在显而易见... <叹气>

// === module3.test.js ===
import {fetchDataFx, $storeA} from 'module1';
import {$storeC} from 'module3';

import 'module2'; // &lt;-- 这解决了问题

describe('some test', () => {
  test('should return true when fetched data is true', async () => {
    const scope = fork({
      handlers: [
        [fetchDataFx, () => Promise.resolve({data: true})],
      ],
      values: [
        [$storeA, {testA: true}],
        // not setting $storeB on purpose, as we want to test whether the fetched data is stored and calculated
      ],
    });

    await allSettled(fetchDataFx, {scope});

    expect(scope.getState($storeC)).toBe(true); // 成功!
  });
});
英文:

The problem turned out to be with imports. The test module must import any module that has some effector computations defined in order for effector to be aware of them. So obvious now ... <sigh>

// === module3.test.js ===
import {fetchDataFx, $storeA} from &#39;module1&#39;;
import {$storeC} from &#39;module3&#39;;

import &#39;module2&#39;; // &lt;-- this solves the problem

describe(&#39;some test&#39;, () =&gt; {
  test(&#39;should return true when fetched data is true&#39;, async () =&gt; {
    const scope = fork({
      handlers: [
        [fetchDataFx, () =&gt; Promise.resolve({data: true})],
      ],
      values: [
        [$storeA, {testA: true}],
        // not setting $storeB on purpose, as we want to test whether the fetched data is stored and calculated
      ],
    });

    await allSettled(fetchDataFx, {scope});

    expect(scope.getState($storeC)).toBe(true); // SUCCEEDS!
  });
});

huangapple
  • 本文由 发表于 2023年7月13日 22:30:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76680545.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定