Jest & Mobx:如何测试处理器的执行?

问题描述 投票:0回答:1

希望任何人都已经克服了这个问题。 代码沙盒

我想检查一下,在更改 appliedIds 后,loadCampaign 将被执行。正如我们在处理器中所说:

addDisposer( self, reaction(() => self.appliedIds, this.loadCampaign), );

那我该怎么做呢?如何在笑话测试中等待反应执行?我看到 here 我可以使用

const reaction = jest.spyOn(mobx, 'reaction');
但我想检查处理器中执行函数的结果。

src/store/filters/campaignFilterStore.ts

import { reaction } from 'mobx';
import { Instance, addDisposer, flow, types } from 'mobx-state-tree';

export const CampaignFull = types.model('CampaignFull', {
  id: types.identifierNumber,
  name: types.string,
  userId: types.number,
});

export type ICampaignFull = Instance<typeof CampaignFull>;

interface ICampaignData {
  id: number;
  name: string;
  userId: number;
}

export const CampaignFilterStore = types
  .model('CampaignFilterStore', {
    appliedIds: types.array(types.number),
    campaignIds: types.array(types.number),
    campaign: types.maybe(CampaignFull),
  })
  .actions((self) => ({
    afterCreate(): void {
      console.log('afterCreate');

      addDisposer(
        self,
        reaction(() => self.appliedIds, this.loadCampaign),
      );
    },
    loadCampaign: flow(function* loadCampaign(): Generator<
      Promise<ICampaignData>,
      void,
      ICampaignData
    > {
      const campaignId = self.appliedIds[0];

      console.log('loadCampaign', campaignId);

      if (!campaignId) {
        return;
      }

      try {
        const data = yield new Promise((res) => {
          setTimeout(() => {
            res({
              id: 1,
              name: 'name',
              userId: 12,
            });
          }, 500);
        });

        self.campaign = CampaignFull.create({
          id: data.id,
          name: data.name,
          userId: data.userId,
        });
      } catch (e) {
        console.error(e);
      }
    }),
    apply(): void {
      self.appliedIds.replace([...self.campaignIds]);
    },
    toggleCampaign(campaign: { id: number; name: string }): void {
      self.campaignIds.push(campaign.id);
    },
  }));

src/store/filters/campaignFilterStore.test.ts

import { isObservable } from 'mobx';
import { CampaignFilterStore } from 'store/filters/campaignFilterStore';

const CAMPAIGN_1 = {
  id: 1,
  name: 'name',
  userId: 12,
};

describe('CampaignFilterStore', () => {
  test('should load campaign by disposer - DOESNT WORK', async () => {
    const campaigns = CampaignFilterStore.create();

    campaigns.toggleCampaign(CAMPAIGN_1);
    expect(campaigns.campaign).toBeUndefined();
    try {
      expect(isObservable(campaigns.appliedIds)).toBe(true);
      campaigns.apply();
      expect(campaigns.appliedIds).toEqual([CAMPAIGN_1.id]);
    } finally {
      // campaign SHOULD be loaded
      expect(campaigns.campaign).not.toBeUndefined();
    }
  });

  test('should load campaign', async () => {
    const campaigns = CampaignFilterStore.create({
      appliedIds: [CAMPAIGN_1.id],
    });

    expect(campaigns.campaign).toBeUndefined();
    await campaigns.loadCampaign();

    expect(campaigns.campaign).not.toBeUndefined();
    expect(campaigns.campaign?.name).toEqual(CAMPAIGN_1.name);
  });
});

reactjs jestjs mobx mobx-state-tree
1个回答
0
投票

self.loadCampaign
动作需要在反应效果回调中显式调用

  addDisposer(
    self,
    reaction(
      () => getSnapshot(self.appliedIds),
      () => self.loadCampaign()
    )
  );

然后在你的测试中可以创建一个间谍

loadCampaign
行动并确保你改变
appliedIds

const campaigns = CampaignFilterStore.create();
const loadCampaignSpy = jest.spyOn(campaigns, 'loadCampaign');
campaigns.setAppliedIds([1,2,3]); // appliedIds should be changed in order to run the effect defined in reaction()
expect(loadCampaignSpy).toHaveBeenCalledTimes(1);

与autorun不同的是,副作用不会在初始化时运行一次,而是在数据表达式第一次返回新值后才运行。

https://mobx.js.org/reactions.html#reaction

© www.soinside.com 2019 - 2024. All rights reserved.