How to unit test inner function(not return) of setup in Vue3?

Viewed 701

I want to test like this.

Case 1: Error

Cannot spy the inner property because it is not a function; undefined given instead.

  • Component.vue
export default {
  setup() {
    function outer() {
      inner();
    }
    function inner() {
      // do something for only outer function
    }
    return { outer };
  }
};
  • Component.spec.js
it('what can I do?', () => {
  wrapper.vm.inner = jest.fn(); // throw error
  wrapper.vm.outer();
  expect(wrapper.vm.inner).toBeCalled();
});

Case 2: Error

  • Component.vue
export default {
  setup() {
    function outer() {
      inner();
    }
    function inner() {
      // ...
    }
    return { outer, inner }; // add inner
  }
};
  • Component.spec.js
it('what can I do?', () => {
  wrapper.vm.inner = jest.fn();
  wrapper.vm.outer();
  expect(wrapper.vm.inner).toBeCalled();
});
  • expect(jest.fn()).toBeCalled()
    • Expected number of calls: >= 1
    • Received number of calls: 0

Case 3: Pass

it('what can I do?', () => {
  wrapper.vm.outer = jest.fn(() => wrapper.vm.inner());
  jest.spyOn(wrapper.vm, 'inner');
  wrapper.vm.outer();
  expect(wrapper.vm.inner).toBeCalled();
});

This case is not pretty...


Can't I get "inner()" without including it in "return"?

These methods pass when implemented in options api. But I want to use only setup().

1 Answers

Self Answer

I found a way. I made a class like this.

Util.js

class Util {
  outer() {
    this.inner();
  }
  inner() {
    // do something...
  }
}

Component.vue

setup() {
  const util = reactive(new Util());
  function call() {
    util.outer();
  }
  return { util, call };
}

Component.spec.js

it('is this way correct?', () => {
  jest.spyOn(wrapper.vm.util, 'outer');
  jest.spyOn(wrapper.vm.util, 'inner');
  await wrapper.vm.call();
  expect(wrapper.vm.util.outer).toBeCalledTimes(1);
  expect(wrapper.vm.util.inner).toBeCalledTimes(1);
});
Related