2017-11-16 8 views
1

안녕하세요, 저는 Jest에서 단위 테스트를 작성하고 있지만, 현재 붙어있는 종류입니다. 계속 진행하고 조언을 구해야합니다. 단위 테스트에서 함수가 호출되었는지 확인하십시오.

export const submitOrder = async (body, key) => { 
    const clientRepo = new ClientRepository(db) 
    const companyRepo = new CompanyRepository(db) 

    const company = await getCompanyByKey(
    companyRepo, 
    key 
); 

    const client = await createClient(
    clientRepo, 
    body 
); 

    await addClientToCompany(
    companyRepo, 
    client.id, 
    company.id 
); 

    .. More things 
} 

I 쉽게 각 기능을 테스트 할 수

( getCompanyByKeycreateClient & addClientToCompany)을 조롱 저장소를 건네.

그러나 내 리포지토리 기능이 호출되었는지 확인하여 submitOrder 함수의 "흐름"을 테스트하고 싶습니다. 그러나 나는 각 저장소의 인스턴스를 필요로 할 것이고, 나는 submitOrder 함수가 될 때까지 인스턴스화하지 않는다.

내 기능을 단위 테스트하는 방법과 비슷합니다.

jest.mock('../repositories/ClientRepository'); 
jest.mock('../repositories/CompanyRepository'); 

test('should be able to submit an order', async() => { 
    const apiKey = 'mocked-super-key'; 
    const body = getMockData(); 

    const result = await submitOrder(body, apiKey); 
    expect(result).toMatchSnapshot(); 
    expect(CompanyRepository.findByKey).toHaveBeenCalled(); 
    expect(ClientRepository.create).toHaveBeenCalled(); 
    expect(CompanyRepository.addClient).toHaveBeenCalled(); 
}); 

당신이 내 저장소가 호출 된 경우 내가 테스트 할 수있는 방법의 어떤 조언이 있습니까?

답변

1

설명하는 문제는 종속성 주입의 동기 부여 요소 중 하나입니다.

단일 예제로 : submitOrder() 코드는 new을 사용하여 특정 구현 ClientRepository의 클라이언트 저장소를 직접 인스턴스화합니다. 대신, 클라이언트 저장소의 인터페이스를 구현하는 객체가 필요하다는 종속성이 있음을 선언 할 수 있습니다. 그런 다음 주변 환경 (buzzword-ese의 "dependency injection container")에 의해 이러한 객체가 제공 될 수 있습니다. 그런 다음 테스트하는 동안 실제 구현 대신 모의 구현을 작성 및 제공 ("삽입")합니다.

이렇게하면 "실제"구현을 여러 개 선택할 수 있어야하는 경우 이미 그렇게 설정되어 있다는 이점이 있습니다.

이렇게하려면 여러 가지 방법이 있습니다. 그것은 디자인 패턴처럼 단순 할 수도 있고,보다 완벽한 솔루션을 위해 의존성 주입 프레임 워크를 사용할 수도 있습니다.

이 연습을 위해 코드를 리펙토링 할 수없는 경우 JavaScript는 동적이어서 new의 호출을 가로 채서 종속성 삽입을 시뮬레이트하는 방법을 함께 사용할 수 있습니다.

+0

그래, 내가 너를 이해했다고 생각해. 다음과 같음 : 'container.register ('companyRepository', new CompanyRepository())'? 내 테스트 스위트에서 'container.register ('companyRepository ', new MockCompanyRepository())'와 동일한 작업을 수행하면 내 모의을 덮어 쓰지 않을까요? – mertje

+0

우리는'container.register ('companyRepository', new CompanyRepository())가 어디에서 발생할지에 대해 상반되는 가정을하고 있다고 생각합니다. 테스트 도중 실행되지 않는 라인입니다. –

+0

맞아요, 그래서 어떤 의존성이 필요한 기능과 어떤 환경 (생산 및 테스트)을 가리 키도록 일부 설정 파일이 필요합니까? – mertje

1

두 번째 매개 변수로 모의 구현 팩토리를 jest.mock, as described in the docs에 전달할 수 있습니다.

이 기능을 사용하면 검사 할 메소드를 조롱 할 수 있습니다.

이 시도 :

jest.mock('../repositories/CompanyRepository',() => { 
    findByKey: jest.fn(), 
    addClient: jest.jn() 
}); 

const mockCreate = jest.fn(); 

jest.mock('../repositories/CompanyRepository',() => class { 
    create(...args) { 
     mockCreate(...args); 
    } 
}); 

test('should be able to submit an order', async() => { 
    const apiKey = 'mocked-super-key'; 
    const body = getMockData(); 

    const result = await submitOrder(body, apiKey); 
    expect(result).toMatchSnapshot(); 
    expect(CompanyRepository.findByKey).toHaveBeenCalled(); 
    expect(ClientRepository.create).toHaveBeenCalled(); 
    expect(CompanyRepository.addClient).toHaveBeenCalled(); 
}); 

이후 CompanyRepository가 생성됩니다 "새로운는"우리는이 경우 클래스 정의를 사용하여 메소드가 호출된다 "만들기"때 호출되는 모의 기능 전달 .

+0

불행히도 내 'CompanyRepository'가 __new__ 키워드로 인스턴스화 되었기 때문에 이것이 작동하지 않습니다. 내가'__mock__' 폴더에 mimic mock을 만들고 대체 할 수는 있지만. 하지만 여전히 내 저장소 기능을 테스트 할 수 없습니다. – mertje

+0

OK, 모의 팩토리에서 클래스를 반환하도록 할 수도 있습니다. 내 코드 예제를 업데이트했습니다. 시도해주세요. –