У меня есть компонент Студенческий компонент следующим образом
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>
Любые предложения, пожалуйста...
Я не видел, как вы издеваетесь над методом 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);» в котором говорится: «При тестировании код, вызывающий обновление состояния реакции, должен быть заключен в действие (...)». Любые предложения здесь, пожалуйста....