테스트 코드

ts-mockito 와 deepEqual 사용하기

후뿡이 2023. 7. 8. 02:25

🐳 문제


 

describe("User Service Test", () => {
    it('should call repository.findOneBy', async () => {
        const user = new User();
        user.name = "Hoo"
        
        const mockedRepository = mock(UserRepository);
        when(mockedRepository.findOneBy({name:user.name})).thenResolve(user);
        
        const repo = instance(mockedRepository);
        const result = await repo.findOneyBy({name:user.naem});

        verify(mockedRepository.findOneBy({name:user.name})).once();
    }) 

})

 

위의 ts-mockito를 활용한 test coded의 결과가 어떻게 될 것이라고 생각하는가 ? 

mockedRepository.findOneBy({name:user.name}) 를 호출할 경우 user 객체를 return 하도록 했다.

그리고 실제로 mockedRepository.findOneBy({name:user.name})가 한 번 호출 되었는지 확인하는 코드를 구현했다. 

결과를 한 번 살펴보자

 

대차게 실패한 것을 알 수 있다.

도대체 왜 그러는 것일까 ?

 

🐳 Javascript의 객체 비교 방법


먼저 이 문제의 해결 방법을 알기 위해서는 Javascript에서 객체를 비교하는 방법을 알아야 한다.

다음의 코드를 보자

obj1 과 obj2는 정확히 같은 값을 같기 때문에 같아야 두 객체를 비교한 결과는 같아야 할 것으로 생각되지 않는가 ?

하지만 결과는 false가 출력됨을 알 수 있다.

 

이는 Javascript에서 객체를 비교하는 방법을 알아야 한다.

 

Javascript는 객체의 값만 비교하는 것이 아니라 메모리 주소를 비교하기 때문에 두 객체의 메모리 주소가 달라 두 객체를 다르다고 판단한다.

 

그렇다면 문제의 test code를 살펴보자

describe("User Service Test", () => {
    it('should call repository.findOneBy', async () => {
        const user = new User();
        user.name = "Hoo"
        
        const mockedRepository = mock(UserRepository);
        when(mockedRepository.findOneBy({name:user.name})).thenResolve(user);
        
        const repo = instance(mockedRepository);
        const result = await repo.findOneyBy({name:user.naem});

        verify(mockedRepository.findOneBy({name:user.name})).once();
    }) 

})

when(mockedRepository.findOneBy({name:user.name})).thenResolve(user)

위의 코드는 {name:user.name}과 정확히 같은 객체 ( 메모리주소까지 ) 가 들어왔을 때에만 user값을 return하게 된다.

하지만 실제로 {name:user.name} 이 객체와 메모리 주소까지 같은 값을 대입하지는 않기 때문에 mockedRepository.findOneBy가 호출되지 않는 것이다 !

 

그렇다면 어떻게 해야할까?

🐳 deepEqual을 사용하자 ! 


 

ts-mockitod는 deepEqual 메소드를 지원한다.

deepEqual 메소드는 두 객체를 비교할 때 두 객체의 값이 같은 지를 확인한다. 메모리 주소까지 같지는 않아도 괜찮다는 뜻이다 !

그러면 이 deepEqual을 사용한 test code는 어떻게 동작할까?

 

describe("User Service Test", () => {
    it('should call repository.findOneBy', async () => {
        const user = new User();
        user.name = "Hoo"
        
        const mockedRepository = mock(UserRepository)
        when(mockedRepository.findOneBy(deepEqual({name:user.name}))).thenResolve(user)
        
        const repo = instance(mockedRepository)
        
        const result = await repo.findOneBy({name:user.name})
        console.log(result.name)

        verify(mockedRepository.findOneBy(deepEqual({name:user.name}))).once()
    }) 

})

when(mockedRepository.findOneBy(deepEqual({name:user.name}))).thenResolve(user)

이번에는 deepEqual을 사용해서 {name:user.name} 과 같은 값을 가지는 객체가 들어오면 user를 던지게 코드를 구성했다.

 

결과를 살펴보자

 

 

너무 아름답게 통과하는 것을 볼 수 있다.

 

저처럼 바보같이 객체를 deepEqual을 사용하지 않고 비교하시는 분들은 조심하시기 바랍니다 ... !!