Как издеваться над вызовом axios

У меня есть компонент Студенческий компонент следующим образом

import axios from 'axios';
import React from 'react';
import { useEffect, useState } from 'react';

function Student(props) {
  const [studentRecord, setStudentRecord] = useState(props.stRecord);
  const [studentSubjects, setStudentSubjects] = useState(null);
  function getStudentSubjects() {
    let apicalladdress = '/studentapi/GetStudentSubjects/' + studentRecord.studentNumber;
    axios.get(apicalladdress).then((result) => {
      setStudentSubjects(result.data);
    });
  }
  useEffect(() => {
    getStudentSubjects();
  }, [studentRecord]);

  return (
    <div>
      <div>{studentRecord.studentNumber}</div>
      <div>{setStudentSubjects[0].subjectName}</div>
    </div>
  );
}

У меня есть тест, созданный, как показано ниже

import {StudentSubjectsData} from "../globalDataProvider";
import AxiosMock from "axios"

it("make sure student renders",async ()=>{
  const mockStudentSubjects=await Promise.resolve({data: StudentSubjectsData()});
  AxiosMock.get.mockResolvedValue(mockStudentSubjects);
  
  render (<Student stRecord = {StudentRecord}/>);
}

Но я получаю следующие ошибки

Ошибка 1. Обновление компонента Student внутри теста не было завернуто в act(...) для строки :setStudentSubjects(result.data);

Ошибка 2. Для следующей строки печати я получаю сообщение об ошибке TypeError: Не удается прочитать свойства неопределенного (чтение subjectName)

<div>{setStudentSubjects[0].subjectName}</div>

Любые предложения, пожалуйста...

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не видел, как вы издеваетесь над методом axios.get(), я буду использовать jest.spyOn(), чтобы издеваться над ним.

Для второй ошибки состояние studentSubjects равно null для первого рендера. Лучше указать пустой массив вместо null в качестве его начального значения. Кроме того, вы можете использовать необязательную цепочку для доступа к значению.

Student.tsx:

import axios from 'axios';
import React from 'react';
import { useEffect, useState } from 'react';

export function Student(props) {
  const [studentRecord, setStudentRecord] = useState(props.stRecord);
  const [studentSubjects, setStudentSubjects] = useState<{ subjectName: string }[]>([]);
  function getStudentSubjects() {
    let apicalladdress = '/studentapi/GetStudentSubjects/' + studentRecord.studentNumber;
    axios.get(apicalladdress).then((result) => {
      setStudentSubjects(result.data);
    });
  }
  useEffect(() => {
    getStudentSubjects();
  }, [studentRecord]);

  return (
    <div>
      <div>{studentRecord.studentNumber}</div>
      <div>{studentSubjects[0]?.subjectName}</div>
    </div>
  );
}

Student.test.tsx:

import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import axios from 'axios';
import React from 'react';
import { Student } from './Student';

describe('75502126', () => {
  test('should pass', async () => {
    const axioGetSpy = jest.spyOn(axios, 'get').mockResolvedValue({ data: [{ subjectName: 'a' }] });
    render(<Student stRecord = {{ studentNumber: 1 }} />);
    expect(await screen.findByText('a')).toBeInTheDocument();
    axioGetSpy.mockRestore();
  });
});

Результат испытаний:

 PASS  stackoverflow/75502126/Student.test.tsx (8.98 s)
  75502126
    ✓ should pass (34 ms)

-------------|---------|----------|---------|---------|-------------------
File         | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------|---------|----------|---------|---------|-------------------
All files    |     100 |      100 |     100 |     100 |                   
 Student.tsx |     100 |      100 |     100 |     100 |                   
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.508 s

Спасибо, Лин Ду, за указание на решение. Я принял ваш ответ. Вы прояснили пару вещей, которые я хотел. Единственное, что у меня есть в той же проблеме, это то, что я все еще получаю сообщение для этой строки «setStudentSubjects (result.data);» в котором говорится: «При тестировании код, вызывающий обновление состояния реакции, должен быть заключен в действие (...)». Любые предложения здесь, пожалуйста....

V R 20.02.2023 14:56

Другие вопросы по теме