next.js Nock JS mocking工具产生错误`'instanceof'的右侧不是对象`

fxnxkyjh  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(83)

我正在尝试使用一个名为Nock JS的工具
https://www.npmjs.com/package/nock
使用Next JSReact演示应用使用Cypress进行测试
·Next.js 13.4
· Cypress 12.17.1
· React 18.2

e2e/homepage.cy.js

describe('weather app spec', () => {
  it('can load the current weather', () => {

    const nock = require('nock')

    const scope = nock('https://api.openweathermap.org')
      .get('/data/2.5/weather')
      .reply(200, {
      "coord":  {
           "lon": -73.9629,
           "lat": 40.6884
      },
      "weather"  :
        [{"id": 211, "main": "scattered clouds", "description": "scattered clouds", "icon": "11d"}, {
          "id": 500,
          "main": "Rain",
          "description": "scattered clouds",
          "icon": "10d"
      }],
      "base" : "stations",
      "main":
      {
        "temp": 299.25,
        "feels_like": 299.25,
        "temp_min": 296.15,
        "temp_max": 303.46,
        "pressure": 1014,
        "humidity": 75
      }

    })

    cy.visit('/')
    cy.get('#__next').should('contain', "Click to get your weather")
    cy.contains('Get Weather').click()

    cy.contains("Current weather is scattered clouds")
  })
})

字符串
如果测试没有nock,则测试通过(预期行为):
x1c 0d1x的数据
当然,我不想每次运行测试时都调用Open weather API,现在测试被硬编码为“分散的云”,它会随着天气的变化而变化。
因此,我希望Nock模拟来自外部API的HTTP响应,并在所有测试运行中将其固定到位
但是,如果我添加scope = nock('https://api.openweathermap.org')行(见上图),我会得到:

Right-hand side of 'instanceof' is not an object



虽然我不认为这与Nock为什么给我这个错误有关,但作为参考,这里是实现代码:

import {useRouter} from 'next/router'
import {useState, useEffect, useRef} from 'react'

export async function getServerSideProps(context) {
  // Fetch data from external API
  const OPEN_WEATHER_MAP_API_KEY = process.env.OPEN_WEATHER_APP_API_KEY

  const query = context.query

  const lat = query.lat
  const long = query.long

  if (lat && long) {
    const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=${OPEN_WEATHER_MAP_API_KEY}`;

    const res = await fetch(url)
      .then(res => res.json())
      .then(
        (result) => {
          if (Number(result.cod) === 200) {
            // success result
            const weatherSummary = result.weather[0].description;
            const k_temp = result.main.temp;
            return {forecastSuccess: true,  weatherSummary, temp: k_temp}
          } else {
            return {forecastSuccess: false}
          }
        }
      )
    return {props: res}
  } else {
    return {props: {}}
  }
}

export default function Home({forecastSuccess, weatherSummary, temp}) {
  const router = useRouter();

  const [lat, setLat] = useState(undefined);
  const [long, setLong] = useState(undefined);

  const getLocationAndWeather =  () => {
    navigator.geolocation.getCurrentPosition(async (location) => {
      setLat(location.coords.latitude)
      setLong(location.coords.longitude)
    })
  }

  useEffect(() => {
    if (lat && long) {
      refreshData();
    }
  }, [lat, long])
  const refreshData = () => {
    router.replace(`${router.asPath}?lat=${lat}&long=${long}`);
  }

  return (
    <>
      <p>Click to get your weather:</p>
      <br />
      <input type={"submit"} onClick={ getLocationAndWeather } data-test-id={'get-weather-button'} value={"Get Weather"}/>

      <h1>
        { forecastSuccess && `Current weather is ${weatherSummary}`}
      </h1>
      <h2>
        { forecastSuccess && `${temp} °F`}
      </h2>
      <br />
    </>
  )
}

k4ymrczo

k4ymrczo1#

NockJS是一个Node库,所以很可能你不能将它导入到测试(在浏览器中运行)中并在那里运行它。
我这里有一个半答案Mocking Next.js getInitialProps in _app可能适合你的需要。
基本上

  • 在NextJs中,SSR几乎不可能在Cypress中模拟API请求,因为服务器在Cypress能够打开网页之前执行请求。
  • 您可以很容易地使用NextJs定制服务器设置“静态”模拟,但这只允许一组模拟数据。
  • 理论上,您可以使用cy.exec()从测试内部启动和停止模拟服务器,并且在cy.visit()之前,您可以设置模拟数据以适应特定的测试。
  • Gleb Bahmutov有一个来自Cypress任务的使用NockJs的example,但它是用Cypress v9编写的,我无法让它升级到最新版本。但如果你想使用旧版本,这是一个可行的方法,也是一个很好的例子,使用NockJs与Cypress,你可能能够适应。

NockJs不兼容NextJs SSR?

有一件事我忘了提,NextJs在他们的示例中展示了实验性的NodeJs fetch()(参见上面的链接)

import { NextPageContext } from 'next'
 
Page.getInitialProps = async (ctx: NextPageContext) => {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  ...

字符串
但是Nock

警告nock目前不兼容Node的实验性native fetch实现。

参见#2397
我提到这一点是为了防止您正在使用NextJs示例。
您可以使用NodeJs http作为替代方案,但这需要您对应用进行降级。

相关问题