[javascript] typescript로 jest의 모의 종속성

다른 파일에서 종속성이있는 모듈을 테스트 할 때. 해당 모듈을 jest.Mocktypescript로 할당 하면 메서드 mockReturnThisOnce(또는 다른 jest.Mock 메서드)가 종속성에 존재하지 않는다는 오류가 발생하는 경우 이는 이전에 입력 되었기 때문입니다. jest.Mock에서 유형을 상속하기 위해 typescript를 얻는 적절한 방법은 무엇입니까?

다음은 간단한 예입니다.

의존

const myDep = (name: string) => name;
export default myDep;

test.ts

import * as dep from '../depenendency';
jest.mock('../dependency');

it('should do what I need', () => {
  //this throws ts error
  // Property mockReturnValueOnce does not exist on type (name: string)....
  dep.default.mockReturnValueOnce('return')
}

나는 이것이 매우 일반적인 사용 사례라고 생각하며 올바르게 입력하는 방법을 모르겠습니다. 어떤 도움이라도 대단히 감사하겠습니다!



답변

유형 캐스팅을 사용할 수 있으며 test.ts다음과 같이 표시됩니다.

import * as dep from '../dependency';
jest.mock('../dependency');

const mockedDependency = <jest.Mock<typeof dep.default>>dep.default;

it('should do what I need', () => {
  //this throws ts error
  // Property mockReturnValueOnce does not exist on type (name: string)....
  mockedDependency.mockReturnValueOnce('return');
});

TS transpiler는 jest.mock('../dependency');유형 변경을 인식하지 못 dep하므로 유형 캐스팅을 사용해야합니다. 가져온 dep것은 유형 정의가 아니기 때문에 typeof dep.default.

Jest와 TS로 작업하면서 찾은 다른 유용한 패턴은 다음과 같습니다.

가져온 요소가 클래스이면 다음과 같이 typeof를 사용할 필요가 없습니다.

import { SomeClass } from './SomeClass';

jest.mock('./SomeClass');

const mockedClass = <jest.Mock<SomeClass>>SomeClass;

이 솔루션은 일부 노드 네이티브 모듈을 모의해야 할 때도 유용합니다.

import { existsSync } from 'fs';

jest.mock('fs');

const mockedExistsSync = <jest.Mock<typeof existsSync>>existsSync;

jest 자동 모의를 사용하지 않고 수동 모의 생성을 선호하는 경우

import TestedClass from './TestedClass';
import TestedClassDependency from './TestedClassDependency';

const testedClassDependencyMock = jest.fn<TestedClassDependency>(() => ({
  // implementation
}));

it('Should throw an error when calling playSomethingCool', () => {
  const testedClass = new TestedClass(testedClassDependencyMock());
});

testedClassDependencyMock()모의 객체 인스턴스를 생성
TestedClassDependency합니다. 클래스, 유형 또는 인터페이스가 될 수 있습니다.


답변

여기에 설명 mockedts-jest것과 같은 도우미를 사용 하십시오.

// foo.spec.ts
import { mocked } from 'ts-jest/utils'
import { foo } from './foo'
jest.mock('./foo')

// here the whole foo var is mocked deeply
const mockedFoo = mocked(foo, true)

test('deep', () => {
  // there will be no TS error here, and you'll have completion in modern IDEs
  mockedFoo.a.b.c.hello('me')
  // same here
  expect(mockedFoo.a.b.c.hello.mock.calls).toHaveLength(1)
})

test('direct', () => {
  foo.name()
  // here only foo.name is mocked (or its methods if it's an object)
  expect(mocked(foo.name).mock.calls).toHaveLength(1)
})

그리고 만약

  • 너는 사용한다 tslint
  • ts-jest 개발 의존성에 있습니다.

이 규칙을에 추가하십시오 tslint.json."no-implicit-dependencies": [true, "dev"]


답변

Mocked에 대한 유형 def 바로 위에 @ types / jest / index.d.ts의 패턴을 사용합니다 (515 행).

import { Api } from "../api";
jest.mock("../api");

const myApi: jest.Mocked<Api> = new Api() as any;
myApi.myApiMethod.mockImplementation(() => "test");


답변

두 가지 솔루션이 있으며 둘 다 원하는 기능을 캐스팅합니다.

1) jest.MockedFunction 사용

import * as dep from './dependency';

jest.mock('./dependency');

const mockMyFunction = dep.myFunction as jest.MockedFunction<typeof dep.myFunction>;

2) jest.Mock 사용

import * as dep from './dependency';

jest.mock('./dependency');

const mockMyFunction = dep.default as jest.Mock;

이 두 솔루션에는 차이가 없습니다. 두 번째 것은 더 짧기 때문에 나는 그것을 사용하는 것이 좋습니다.

두 캐스팅 솔루션 모두 mockMyFunctionlike mockReturnValue또는 https://jestjs.io/docs/en/mock-function-api.html 에서 jest mock 함수를 호출 할 수 mockResolvedValue
있습니다.

mockMyFunction.mockReturnValue('value');

mockMyFunction 예상에 일반적으로 사용할 수 있습니다.

expect(mockMyFunction).toHaveBeenCalledTimes(1);


답변

캐스트 as jest.Mock

단순히 함수를로 캐스팅하면 jest.Mock트릭을 수행 할 수 있습니다.

(dep.default as jest.Mock).mockReturnValueOnce('return')


답변

다음은 jest@24.8.0ts-jest@24.0.2로 수행 한 작업입니다 .

출처:

class OAuth {

  static isLogIn() {
    // return true/false;
  }

  static getOAuthService() {
    // ...
  }
}

테스트:

import { OAuth } from '../src/to/the/OAuth'

jest.mock('../src/utils/OAuth', () => ({
  OAuth: class {
    public static getOAuthService() {
      return {
        getAuthorizationUrl() {
          return '';
        }
      };
    }
  }
}));

describe('createMeeting', () => {
  test('should call conferenceLoginBuild when not login', () => {
    OAuth.isLogIn = jest.fn().mockImplementationOnce(() => {
      return false;
    });

    // Other tests
  });
});

이것은 기본이 아닌 클래스를 모의하는 방법이며 정적 메서드입니다.

jest.mock('../src/to/the/OAuth', () => ({
  OAuth: class {
    public static getOAuthService() {
      return {
        getAuthorizationUrl() {
          return '';
        }
      };
    }
  }
}));

여기에 클래스 유형에서 jest.MockedClass이와 비슷한 유형으로 변환해야합니다 . 그러나 그것은 항상 오류로 끝납니다. 그래서 직접 사용했고 효과가있었습니다.

test('Some test', () => {
  OAuth.isLogIn = jest.fn().mockImplementationOnce(() => {
    return false;
  });
});

하지만 함수라면 조롱하고 타입 대화를 할 수 있습니다.

jest.mock('../src/to/the/Conference', () => ({
  conferenceSuccessDataBuild: jest.fn(),
  conferenceLoginBuild: jest.fn()
}));
const mockedConferenceLoginBuild = conferenceLoginBuild as
jest.MockedFunction<
  typeof conferenceLoginBuild
>;
const mockedConferenceSuccessDataBuild = conferenceSuccessDataBuild as
jest.MockedFunction<
  typeof conferenceSuccessDataBuild
>;


답변

나는 이것을 발견했다 @types/jest:

/**
  * Wrap a function with mock definitions
  *
  * @example
  *
  *  import { myFunction } from "./library";
  *  jest.mock("./library");
  *
  *  const mockMyFunction = myFunction as jest.MockedFunction<typeof myFunction>;
  *  expect(mockMyFunction.mock.calls[0][0]).toBe(42);
*/

참고 :const mockMyFunction = myFunction 다음과 같은 작업을 수행 mockFunction.mockReturnValue('foo')하면 변경 myFunction됩니다.

출처 : https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/jest/index.d.ts#L1089