Jest not.toThrowError() not working in test with jest.spyOn(component.methods, 'mymethod')

Viewed 714

I am trying to make a test for my Nuxt/Vue component method that checks whether or not there was an error.

So what I have done is created a "spy" for this method of interest const spyGetNumberOfResults = jest.spyOn(SearchTable.methods, 'getNumberOfResults'), and then I am expecting it expect(spyGetNumberOfResults).not.toThrowError(), however I am getting an odd error, where it's saying one of my variables inside my method of interest is undefined. This is the error:

TypeError: Cannot set property 'countLoading' of undefined

      571 |         async getNumberOfResults () {
      572 |             // Kick off loader to signal retrieving counts
    > 573 |             this.countLoading = true;
          | ^
      574 | 
      575 |             // Initialize count
      576 |             this.count = '';

      at getNumberOfResults (components/core/SearchTable.vue:573:1)
      at Object.<anonymous> (node_modules/expect/build/toThrowMatchers.js:81:11)
      at Object.toThrowError (node_modules/expect/build/index.js:342:33)
      at Object.<anonymous> (test/SearchTable.spec.js:150:57)

and this is my test code:

test(`GET /${MODEL[1][MAIN_MODULES[i]].subModules[j].backEndFilters.mainModule}/${MODEL[1][MAIN_MODULES[i]].subModules[j].backEndFilters.subModule}/`, async () => {
    const API_ENDPOINT = process.env.NODE_ENV;
    // Initialize our variables
    let success = '';
    let responseData;
    let url = `${API_ENDPOINT}${store.state.core.group.current.id}/${MODEL[1][MAIN_MODULES[i]].subModules[j].backEndFilters.mainModule}/${MODEL[1][MAIN_MODULES[i]].subModules[j].backEndFilters.subModule}?${MODEL[1][MAIN_MODULES[i]].subModules[j].backEndFilters.limit}&fields=`;
    
    // Add fields/columns to be searched on to url
    MODEL[1][MAIN_MODULES[i]].subModules[j].allHeaders.map((header) => {
        if (header.active === true) {
            url += header.value + ',';
        }
    });

    // Remove trailing comma so the sql query doesn't break
    url = url.slice(0, -1);
    
    // Send HTTP GET request
    await axios.get(url, { headers: { Authorization: `Bearer ${localStorage.getItem("access-token")}` } })
        .then(response => {
            success = response.data.success;
            responseData = response;
        })
        .catch(error => console.log('Error:', error));
    
    // Check if HTTP request was successful
    expect(success).toBe(true);

    // Set-up wrapper options
    const wrapperOptions = {
        localVue,
        propsData: {
            searchModule: MODEL[1][MAIN_MODULES[i]].subModules[j],
            query: 'test'
        },
        mocks: {
            $axios: {
                create: () => {
                    return {
                        baseURL: API_ENDPOINT,
                        headers: `Bearer ${localStorage.getItem("access-token")}`,
                        get: jest.fn(() => Promise.resolve(responseData))
                    };
                },
            }
        }
    };
    
    // Prep spies for our component methods we want to validate
    const spyGetNumberOfResults = jest.spyOn(SearchTable.methods, 'getNumberOfResults');
    const spySearch = jest.spyOn(SearchTable.methods, 'search');

    // Mount the component we're testing
    const wrapper = mount(SearchTable, wrapperOptions);

    // Set component data variable
    wrapper.setData({
        count: 0,
        countLoading: false,
        // If true, debug lines log to console, else they don't, set to false prior to release
        debug: false,
        dialog: false,
        intraTableDialog: false,
        expanded: [],
        expandableDataCheck: false,
        frontEndFilters: [],
        itemsOnScreen: null,
        generalSearch: '',
        ignoreCount: false,
        // Set this to true for the test
        regen: true,
        results: [],
        strictSearch: false,
        selectedColumnHeaders: [],
        stagedHeaders: [],
        correctStagedHeaders: [],
        selected: [],
        tableLoading: false,
        intraTableQuery: ''
    })

    // Trigger initial search method to get # of results
    wrapper.vm.getNumberOfResults();

    // Wait for DOM to update
    await wrapper.vm.$nextTick();
    
    // Check if the method was actually called
    expect(spyGetNumberOfResults).toHaveBeenCalled();
    
    // Expect no error from the promise in the function
    expect(spyGetNumberOfResults).not.toThrowError();

    // Expect there the count to be greater than or equal to 0
    expect(parseInt(wrapper.vm.count)).toBeGreaterThanOrEqual(0);

    // Wait for DOM to update
    await wrapper.vm.$nextTick();

    // Check to see if the "search" method was triggered after receiving results
    expect(spySearch).toHaveBeenCalled();
});

However, if I just comment out the line:

expect(spyGetNumberOfResults).not.toThrowError();

I get no errors and my test passes, so there is clearly something wrong with how I am using "not.toThrowError()", but the error message is not very informative to me, someone suggested I add {"loose": true} to my .babelrc config file but this did nothing, I am new to Jest and don't know why this is happening, any assistance is appreciated, thanks in advance.

1 Answers

toThrowError or not.toThrowError must be called not on the spy function. There is good example from docs:

test('throws an error', () => {
  expect(() => {
    SearchTable.getNumberOfResults(); // There must be your call
  }).toThrow();
});
Related