如何模拟属于内部对象的方法

时间:2019-09-03 16:57:26

标签: typescript unit-testing vuejs2 jestjs

是否可以模拟属于我在UnderTest类中拥有的对象的方法。

发出子组件的事件时,执行

Update方法。我想模拟service.saveNewElement(data),这可以让我在then()块中测试数据

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { Service } from 'secret';
import ROUTES from '../../../../router/routes.const';


@Component({
    name: 'UnderTest',
    template: require('./underTest.component.html'),
})
export default class UnderTest extends Vue {
    private service: Service;

    constructor() {
        super();
        this.service = new Service();
    }

    public update(data: any): void {
        this.service
            .saveNewElement(data)
            .then(() => {
                //stuff to do
            })
            .catch(() => {
                this.$notify.error('Oops!, sth went wrong...');
            });
    }

}
</script>

有人知道这样做的方法吗?

编辑:

@ slideshowp2的提示有效,但是我还有另一个问题。

我已经用过

jest.mock('../../services/customer.service',() => ({
    constructor: jest.fn(() => {}),
    saveNewCustomer: jest.fn(() => Promise.resolve({ data: 3 }))
}));

在我的测试文件中。然后我遇到了类似[Vue warn]: Error in data(): "TypeError: service.Service is not a constructor"

的错误

有人知道解决此问题的方法吗?

1 个答案:

答案 0 :(得分:1)

您可以手动模拟使用Service导入的jest.mock(moduleName)并将模拟的Service放入__mocks__目录,我为您的问题提供了一个示例。

文件结构为:

.
├── __mocks__
│   └── someService.ts
├── index.spec.ts
├── index.ts
└── someService.ts

someService.ts

class SomeService {
  public async saveNewElement(data) {
    return 'real data';
  }
}

export { SomeService };

index.ts

import { SomeService } from './someService';

export default class UnderTest {
  private service: SomeService;

  constructor() {
    this.service = new SomeService();
  }

  public update(data: any): any {
    return this.service.saveNewElement(data).then(res => {
      // stuff to do
      console.log(res);
    });
  }
}

__mocks__/someService.ts

const mockedSomeService = {
  saveNewElement: jest.fn().mockResolvedValue('mocked data')
};
const SomeService = jest.fn(() => mockedSomeService);

export { SomeService, mockedSomeService };

单元测试:

import UnderTest from './';

jest.mock('./someService.ts');

const underTest = new UnderTest();

describe('UnderTest', () => {
  it('t1', async () => {
    console.log = jest.fn();
    await underTest.update('jest');
    expect(console.log).toBeCalledWith('mocked data');
  });
});

单元测试结果:

 PASS  src/stackoverflow/57775960/index.spec.ts
  UnderTest
    ✓ t1 (14ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.911s, estimated 2s

=================更新===============

您也可以在没有jest.mock(path, moduleFactory)目录的情况下使用__mocks__模拟导入的模块。

import UnderTest from './';

const mockedSomeService = {
  saveNewElement: jest.fn().mockResolvedValue('mocked data')
};

jest.mock('./someService.ts', () => {
  return {
    SomeService: jest.fn(() => mockedSomeService)
  };
});

const underTest = new UnderTest();

describe('UnderTest', () => {
  it('t1', async () => {
    console.log = jest.fn();
    await underTest.update('jest');
    expect(console.log).toBeCalledWith('mocked data');
  });
});

P.S。使用DIP时很容易测试,因此与导入依赖项相比,可以更轻松地模拟和注入依赖项。您最好导入(取决于)抽象(接口/抽象类),而不是具体的类(SomeService