ts-mockito 와 deepEqual 사용하기
🐳 문제
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을 사용하지 않고 비교하시는 분들은 조심하시기 바랍니다 ... !!