【问题标题】:Unit Test for a function with API call in JasmineUnit Test for a function with API call in Jasmine
【发布时间】:2022-12-02 06:07:33
【问题描述】:

I have a utility function defined in my utils.tsx file:

// resolveAxiosInstance creates an axios instance
const createAxiosInstance = resolveAxiosInstance();

export const getItemList = params => {
    const axios = await createAxiosInstance;
    const res = await axios.get("/my-url", {params});
    return res.data;
}

And I am using the getItemList utility in my component mycomponent.tsx. It is invoked on click of a button but before calling that API the click event sets some states as well. Here's the code of my component:

export const MyComponent = () => {
    //rest of component code
    const clickMe = () => {
        setIsLoading(true);
        const data = {
            // item and price are vars whose values are filled by user through input text
            itemName: item,
            itemPrice: price,
        };
        getItemList(data).then(res => {
            if (res)  {
                setItemData({
                    itemName: name, 
                    itemPrice: price, 
                    itemDiscount: res.disc,
                });
            }
        }, err => console.log(err));
    }
    return (
        //rest of the component code
        <div>
            <Button onClick={clickMe} data-testid="update">Click Me</Button>
        </div>
    )
}

I want to write a unit test case in Jasmine to test the on click functionality. I am able to invoke the on click function by using simulate("click") on the button element. But it doesn't execute the API call and that's understandable. To execute the API call I tried to use spyOn but it didn't help. It returns the error that getItemList is not declared configurable. Here's my test case:

it("should show data on click me", () => {
    const wrapper = mount(<MyComponent />);
    let elem = wrapper.find(MyComponent);
    const mockSpy = Jasmine.createSpy("getItemList").and.returnValue(Promise.resolve(mockResp))
    let btn = elem.find('[data-testid="update"]');
    btn.at(0).simulate("click");
    elem = elem.update();
    expect(elem.find("table").length).toBe(1);
});

My question is how can I write a unit test for my use case where I trigger a button click and it calls a function which does something, and then calls an API and updates the table on my view as per the API response.

【问题讨论】:

    标签: javascript reactjs jasmine


    【解决方案1】:

    You can mock fetch or XMLHttpRequest which used by axios. jasmine has official jasmine-ajax library which allows mocking XMLHttpRequest objectbut notfetch. I think that in 99% axios will pick the fetch instead of old XMLHttpRequest so I recommend to use something like fetch-mock

    it("should show data on click me", /*⚠️*/async () => {
        /*⚠️*/fetchMock.mock('/my-url', {data: {disc: 'foo'}});
        const wrapper = mount(<MyComponent />);
        let elem = wrapper.find(MyComponent);
        const mockSpy = Jasmine.createSpy("getItemList").and.returnValue(Promise.resolve(mockResp))
        let btn = elem.find('[data-testid="update"]');
        btn.at(0).simulate("click");
        elem = elem.update();
    
        // because fetch async we should wait response
        expectAsync(/*⚠️*/(await waitFor("table")).length).toBe(1); 
    
        function waitFor(selector) {
            return new Promise((resolve) => {
               funciton checkSelector() {
                 const result = elem.find(selector);
                 if (result.length) return resolve(result);
                 setTimeout(checkSelector);
               }
            });
        }
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-27
      • 1970-01-01
      • 2013-03-07
      • 1970-01-01
      • 2022-12-26
      相关资源
      最近更新 更多