1

I'm having below setup in my project, whenever I extends the httpService and use the 'this.instance' in any service I'm getting the error.

If I use axios.get directly without any interceptors in my service files its working fine.

Im new to the unit testing and badly stuck with this. Please share your comments below. It'll be really helpful.

httpClient.ts

 import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
 import { DEFAULT_HEADERS, HOST } from './ApiHelper';
    
    export abstract class HttpService {
      protected readonly instance: AxiosInstance;
    
      public constructor(requestConfig: AxiosRequestConfig) {
        this.instance = axios.create(requestConfig);
    
        this.instance.interceptors.request.use((request) => {
          request.baseURL = HOST;
          request.headers = { ...DEFAULT_HEADERS };
          return request;
        });
    
        this.instance.interceptors.response.use(
          (response) =>
            response,
          (error) =>
            new Promise((resolve, reject) => {
              reject(error.response);
            }),
        );
      }
    }
    
    export default HttpService;

someService.ts

    import HttpService from './HttpService';
    
    const warningListUrl = 'some/url';
    
    class SomeService extends HttpService {
      public constructor() {
        super({
        });
      }
    
      public async getSomething(params: any) {
        this.instance({
          method: 'GET',
          url: warningListUrl,
          params,
        }).then((res) =>
          res.data);
      }
    }

export default SomeService;

ReactComponent.tsx

const fetchList = async () => {
    try {
      setIsLoading(true);
      const someService = new SomeService();
      const response: any = await someService.getSomething({});
      setWarnings(response.content);
      setTotalPages(response.totalPages);
    } catch (error) {
      console.log(error);
    } finally { setIsLoading(false); }
  };

  useEffect(() => {
    fetchList();
  }, []);

ReactComponent.test.tsx

jest.mock('../../services/SomeService');
const someService = new SomeService();


describe('page tests', () => {
  test('page renders without crashing', async () => {
    (someService.getWarningList as jest.Mock).mockResolvedValue(someMatchingData);
    await act(async () => {
      render(<ReactComponent />);
    });
    const text = screen.getByText('Warning 1');
    expect(text).toBeInTheDocument();
  });
}

Error:

TestingLibraryElementError: Unable to find an element with the text: Warning 1. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

render(<Warning />);
});
-> const text = screen.getByText('Warning 1');
 expect(text).toBeInTheDocument();
});
Ajithkumar S
  • 859
  • 7
  • 16
  • You mocked SomeService but didnt implement any methods, so mockImplementation for SomeService is needed. jest.mock('../../services/SomeService', ()=> // implement what this module should return here) – JunKim Jun 28 '22 at 16:30
  • @JunKim thanks for the response. lets say i have multiple methods inside a service, should I return values for each methods? Can you please help me with some more details? :| – Ajithkumar S Jun 28 '22 at 16:54

2 Answers2

0

You could use requireActual if you need to mock only specific methods.

jest.mock('../../services/SomeService', ()=> {
  return {
    ...jest.requireActual('../../services/SomeService'),
    getWarningList: new Promise.resolve(someMatchingData)
  }
})

How about mocking a module like this?

JunKim
  • 647
  • 7
  • 17
  • Still same issue. If I use a static function and skip the HttpService extend, it works fine. But i need interceptors. we are missing something else. :| static async getSomething(payload ) { const url = ''someUrl const response = await axios.get(url, { headers: { ...DEFAULT_HEADERS } }); return response.data; } – Ajithkumar S Jun 29 '22 at 03:27
0

Accessing methods through 'prototype' saved my day.

(someService.prototype.getWarningList as jest.Mock).mockResolvedValue(someMatchingData);

just adding it above the test description saved me.

Ajithkumar S
  • 859
  • 7
  • 16