Search code examples
javascriptvue.jsjestjsvue-test-utils

How to mock a user module differently in each test?


I have the following unit test for my Vue component:

import { shallowMount } from '@vue/test-utils';
import OrganizationChildren from './OrganizationChildren.vue';

describe('OrganizationChildren', () => {
  beforeEach(() => {
    jest.resetModules();
  });

  it('passes', () => {
    jest.doMock('@/adonis-api', () => {
      return {
        organization: {
          family(id) {
            return {
              descendants: [],
            };
          },
        },
      };
    });

    const wrapper = shallowMount(OrganizationChildren, {
      propsData: {
        org: {
          id: 1,
        },
      },
    });
  });
});

And in the Vue component, it does import { organization } from '@/adonis-api';. I'm temporarily just console.logging the imported organization object, to make sure it's correct. But I can see that it's not using the mocked version that I've specified. What am I doing wrong? My goal is to mock the family method differently in each it() block to test what happens if descendants is empty, if it contains 5 items, 100 items, etc.


Solution

  • Solved! I had a couple issues, as it turns out:

    1. Not properly mocking @/adonis-api. I should mention that it only mocks stuff at the top level, so I had to use a factory function in jest.mock (see below).
    2. I needed an await flushPromises() to allow the template to re-render after its created() method evaluated my mock function and stored the result in this.children.

    Full test:

    import { shallowMount, config } from '@vue/test-utils';
    import flushPromises from 'flush-promises';
    import OrganizationChildren from './OrganizationChildren.vue';
    import { organization } from '@/adonis-api';
    
    jest.mock('@/adonis-api', () => ({
      organization: {
        family: jest.fn(),
      },
    }));
    
    describe('OrganizationChildren', () => {
      config.stubs = {
        'el-tag': true,
      };
    
      it('shows nothing when there are no children', async () => {
        organization.family.mockResolvedValueOnce({
          descendants: [],
        });
    
        const wrapper = shallowMount(OrganizationChildren, {
          propsData: {
            org: {
              id: 1,
            },
          },
        });
    
        await flushPromises();
        const h4 = wrapper.find('h4');
    
        expect(h4.exists()).toBe(false);
      });
    
      it('shows children when provided', async () => {
        organization.family.mockResolvedValueOnce({
          descendants: [{ name: 'One' }, { name: 'Two' }],
        });
    
        const wrapper = shallowMount(OrganizationChildren, {
          propsData: {
            org: {
              id: 1,
            },
          },
        });
    
        await flushPromises();
        const h4 = wrapper.find('h4');
        const list = wrapper.findAll('el-tag-stub');
    
        expect(h4.exists()).toBe(true);
        expect(list.length).toBe(2);
        expect(list.at(0).text()).toBe('One');
        expect(list.at(1).text()).toBe('Two');
      });
    });