在_app中模拟Next.js getInitialProps

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

我正在尝试找到一种方法来嘲笑

Next.js
getInitialProps

我目前正在使用 Cypress 运行 e2e 测试,但我找不到一种方法来模拟服务器端获取,而不需要启动模拟服务器来进行获取。我很好奇是否有人找到了更好的方法?

next.js cypress server-side-rendering
1个回答
16
投票

从 NextJs 文档的这一页开始:NextJs - getInitialProps

很高兴知道:

getInitialProps
是一个旧版 API。我们建议使用
getStaticProps
getServerSideProps
代替。

我决定仅使用

getServerSideProps
- 希望这能转化为您特定的 SSR 方法。


之前的例子

Gleb Bahmutov 在此处有一篇关于此问题的博客使用 Next.js getServerSideProps 调用时模拟网络,但它是 Cypress v9 项目,并且存储库尚未更新到 Cypress 10+(这不是一个好兆头)。

无论如何,我尝试在 Cypress 12.17.0 中运行此存储库,但 NextJs 服务器不断重新启动 Cypress GUI(反之亦然),因此我猜测有关不在 Cypress 节点进程内启动服务器的警告是有效的。


使用 NextJs 自定义服务器

参考:NextJs 自定义服务器

自定义 Next.js 服务器允许您以 100% 编程方式启动服务器,以便使用 自定义服务器模式

实际上我用的是GeeksForGeeks上的那个,但我认为你使用哪一个并不重要。

以 Gleb 的应用程序和规范为起点,我向应用程序的

global.fetch()
调用中使用的
getServerSideProps
方法添加了一个简单的补丁。

步骤是

  • 使用您想要测试的模拟数据创建一个
    mocks.json
    文件
  • 启动自定义服务器
  • 导航至
    localhost:3000
    检查应用程序是否已启动
  • 启动
    cypress open
    并运行规范

/服务器/server.js

使用

/node ./server/server.js
在终端中运行或添加
package.json
脚本。

const next = require('next')
const http = require('http')
const mocks = require('./mocks.json')

const app = next({dev: process.env.NODE_ENV !== 'production'})

/* Cypress mocking for getServerSideProps */
const originalFetch = global.fetch
global.fetch = (url) => {
  const mock = mocks[url]
  if (mock) {
    return new Response(JSON.stringify(mock.body), {status: mock.status})
  } else {
    return originalFetch(url)
  }
}

/* "standard" NextJs custom server */
app.prepare().then(() => {
 const server = http.createServer((req, res) => {
  console.log('req.url', req.url)
   // Handle API routes
   if (req.url.startsWith('/api')) {
     // Your API handling logic here
   } else {
     // Handle Next.js routes
     return app.getRequestHandler()(req, res)
   }
 })
 server.listen(3000, (err) => {
   if (err) throw err
   console.log('> Ready on http://localhost:3000')
 })
})

/server/mocks.json

{
  "https://icanhazdadjoke.com/": {  // exact match to URL called in the app
    "statusCode": 200,
    "body": {
      "id": "NmbFtH69hFd",
      "joke": "Our wedding was so beautiful, even the cake was in tiers",
      "status": 200
    }
  }
}

/cypress/e2e/spec.cy.js

const mocks = require('../../server/mocks.json')

it('getServerSideProps returns mock', () => {
  cy.visit('http://localhost:3000')

  cy.get('[data-cy="joke"]')
    .should('have.text', mocks['https://icanhazdadjoke.com/'].body.joke)
})

结果

enter image description here

删除实现模拟的 server.js 块

enter image description here

限制

您无法在 Cypress 测试中动态设置模拟数据,因为服务器在测试开始之前就已经运行了。

也许可以使用

cy.exec()
来启动和停止服务器,但我没有尝试过。

如果可以重新启动服务器,则可以从测试内部更改

mocks.json
,但我很高兴在静态文件中设置模拟,因为它降低了复杂性。

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