由于反应导航生成的密钥,Jest 快照测试失败

Gra*_*ane 5 jestjs react-native react-navigation

我的 Jest 测试失败,因为每次运行测试时密钥中的时间戳都不同:

\n\n
 FAIL  ./App.test.js\n  \xe2\x9c\x95 renders without crashing (72ms)\n\n  \xe2\x97\x8f renders without crashing\n\nexpect(value).toMatchSnapshot()\n\nReceived value does not match stored snapshot 1.\n\n- Snapshot\n+ Received\n\n@@ -347,11 +347,11 @@\n              "index": 0,\n              "isTransitioning": false,\n              "key": "StackRouterRoot",\n              "routes": Array [\n                Object {\n-                 "key": "id-1519567169760-0",\n+                 "key": "id-1519567814666-0",\n                  "routeName": "Menu",\n                },\n              ],\n            },\n          }\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的 App.js 文件:

\n\n
import React from \'react\';\nimport { StackNavigator } from \'react-navigation\';\nimport Menu from \'./components/Menu\';\nimport List from \'./components/List\';\n\nconst RootStack = StackNavigator(\n  {\n    Menu: {\n      screen: Menu,\n    },\n    List: {\n      screen: List,\n    },\n  },\n  {\n    initialRouteName: \'Menu\',\n  }\n);\n\nexport default class App extends React.Component {\n   render() {\n     return <RootStack />;\n   }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的测试文件:

\n\n
import React from \'react\';\nimport App from \'./App\';\n\nimport renderer from \'react-test-renderer\';\n\ntest(\'renders without crashing\', () => {\n  const rendered = renderer.create(<App />).toJSON();\n  expect(rendered).toBeTruthy();\n  expect(rendered).toMatchSnapshot();\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

是否可以覆盖键值,或者是否有办法在测试运行时忽略键?

\n

Eli*_*iot 4

较新版本的 jest 还支持属性匹配器,允许使用匹配器评估快照的某些部分,而不是要求整个快照相同。

下面是一个示例,展示了使用此功能来解决OP问题的几种不同方法:

it('Should ignore route keys in snapshot', () => {
  const testObject = {
    index: 0,
    isTransitioning: false,
    key: 'StackRouterRoot',
    routes: [
      {
        key: `id-${Date.now()}-0`,
        routeName: 'Menu',
      },
      {
        key: `id-${Date.now()}-1`,
        routeName: 'Splash',
      },
    ],
  };

  expect(testObject).toMatchSnapshot({
    routes: [
      {
        key: expect.stringMatching(/id-\d+?-\d/),
        routeName: 'Menu',
      },
      {
        key: expect.stringMatching(/id-\d+?-\d/),
        routeName: 'Splash',
      },
    ],
  }, 'Explicitly list all routes');

  expect(testObject).toMatchSnapshot({
    routes: expect.arrayContaining([
      expect.objectContaining({
        key: expect.stringMatching(/id-\d+?-\d/),
      }),
    ]),
  }, 'Match any route');
});
Run Code Online (Sandbox Code Playgroud)

它会产生以下快照:

exports[`<App /> Should ignore route keys in snapshot: Explicitly list all routes 1`] = `
Object {
  "index": 0,
  "isTransitioning": false,
  "key": "StackRouterRoot",
  "routes": Array [
    Object {
      "key": StringMatching /id-\\\\d\\+\\?-\\\\d/,
      "routeName": "Menu",
    },
    Object {
      "key": StringMatching /id-\\\\d\\+\\?-\\\\d/,
      "routeName": "Splash",
    },
  ],
}
`;

exports[`<App /> Should ignore route keys in snapshot: Match any route 1`] = `
Object {
  "index": 0,
  "isTransitioning": false,
  "key": "StackRouterRoot",
  "routes": ArrayContaining [
    ObjectContaining {
      "key": StringMatching /id-\\\\d\\+\\?-\\\\d/,
    },
  ],
}
`;
Run Code Online (Sandbox Code Playgroud)

我最近遇到的另一个可能有帮助的笑话功能是自定义快照序列化器。使用此功能,我认为您可以为路由对象添加一个序列化器,该序列化器将在序列化之前删除密钥或将其替换为静态值。我现在无法提供示例,因为我尚未使用此功能,但它似乎值得一提。