I have a component Student component as follows
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>
);
}
I have a test created as below
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}/>);
}
But I am getting following errors
Error 1. An update to Student component inside a test was not wrapped in act(...) for line :setStudentSubjects(result.data);
Error 2. For following print line, I am getting error TypeError: Cannot read properties of undefined (reading subjectName)
<div>{setStudentSubjects[0].subjectName}</div>
Any suggestions please...
I didn't see how you mock the axios.get()
method, I will use jest.spyOn()
to mock it.
For the second error, the studentSubjects
state is null
for the first render. It's better to give an empty array instead of null
as its initial value. Besides, you can use optional chain to access the value.
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();
});
});
Test result:
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