[javascript] MobX의 테스트 방법

MobX는 JavaScript 애플리케이션 상태 관리를 간편하게 해주는 라이브러리입니다. 애플리케이션의 상태 변화를 관찰하고, 자동으로 업데이트를 수행할 수 있도록 도와줍니다. 이번 포스팅에서는 MobX를 어떻게 테스트할 수 있는지 알아보겠습니다.

Mocking을 통한 테스트

MobX는 코드 베이스 내에서 observable과 같은 특정 동작을 사용합니다. 테스트를 작성할 때, 이러한 동작을 Mock으로 대체하여 테스트할 수 있습니다. 예를 들어, 특정 값을 observable로 만들려면 @observable을 사용하게 되는데, 테스트에서는 이를 jest.fn() 등으로 대체할 수 있습니다.

예를 들어, 다음과 같은 코드가 있다고 가정해봅시다.

import { observable } from 'mobx';

class CounterStore {
  @observable count = 0;

  increment() {
    this.count++;
  }
}

이 코드를 테스트하기 위해서는, CounterStore 인스턴스를 생성하고 increment 메소드가 호출되었을 때 count 값이 적절히 증가하는지를 확인해야 합니다. 이를 위해 다음과 같은 테스트 코드를 작성할 수 있습니다.

import { observable } from 'mobx';
import CounterStore from './CounterStore';

jest.mock('mobx', () => ({
  observable: jest.fn((value) => value),
}));

describe('CounterStore', () => {
  it('should increment count', () => {
    const counterStore = new CounterStore();
    counterStore.increment();
    expect(counterStore.count).toBe(1);
  });
});

위의 예시에서는 mobx.observablejest.fn()으로 대체하여 observable으로 값을 전달하도록 만들었습니다. 이를 통해 테스트 중에 실제 MobX 동작을 수행하지 않고도, count 값이 증가하는지 확인할 수 있습니다.

독립적인 테스트

MobX를 테스트할 때는 독립적으로 테스트가 이루어지도록 주의해야 합니다. MobX는 전역적인 상태 관리가 가능한데, 이로 인해 하나의 테스트가 다른 테스트에 영향을 줄 수 있습니다.

예를 들어, 다음과 같은 코드가 있다고 가정해봅시다.

import { observable } from 'mobx';

class UserStore {
  @observable user = {
    name: 'John',
    age: 30,
  };

  changeAge(age) {
    this.user.age = age;
  }

  changeName(name) {
    this.user.name = name;
  }
}

위의 코드에서 user 객체는 MobX의 observable로 정의되어 있습니다. 만약 다음과 같은 테스트 코드를 작성한다면,

import { observable } from 'mobx';
import UserStore from './UserStore';

describe('UserStore', () => {
  it('should change user age', () => {
    const userStore = new UserStore();
    userStore.changeAge(35);
    expect(userStore.user.age).toBe(35);
  });

  it('should change user name', () => {
    const userStore = new UserStore();
    userStore.changeName('Jane');
    expect(userStore.user.name).toBe('Jane');
  });
});

첫 번째 테스트에서 userStore.changeAge(35)를 호출하여 userage를 변경하는 동작을 수행합니다. 그리고 두 번째 테스트에서 userStore.changeName('Jane')을 호출하여 username을 변경합니다. 하지만 두 개의 테스트는 독립적으로 실행되지 않습니다. 첫 번째 테스트에서 user의 상태가 변경되어, 두 번째 테스트는 예상치 못한 결과를 반환하게 됩니다.

이러한 문제를 해결하기 위해서는 각각의 테스트에서 새로운 인스턴스를 생성하여 독립적으로 실행되도록 해야 합니다. 위의 예시에서는 beforeEach를 사용하여 각 테스트가 실행되기 전에 새로운 인스턴스를 생성하도록 하면 됩니다.

import { observable } from 'mobx';
import UserStore from './UserStore';

describe('UserStore', () => {
  let userStore;

  beforeEach(() => {
    userStore = new UserStore();
  });

  it('should change user age', () => {
    userStore.changeAge(35);
    expect(userStore.user.age).toBe(35);
  });

  it('should change user name', () => {
    userStore.changeName('Jane');
    expect(userStore.user.name).toBe('Jane');
  });
});

위의 코드에서 beforeEach 함수를 사용하여 userStore 변수를 초기화하였습니다. 이를 통해 각 테스트가 실행되기 전에 새로운 인스턴스를 생성하도록 하였기 때문에, 테스트 간에 독립성이 보장됩니다.

마치며

이번 포스팅에서는 MobX를 테스트하는 방법을 알아보았습니다. MobX를 테스트할 때는 Mocking을 활용하고, 각 테스트는 독립적으로 실행될 수 있도록 주의해야 합니다. 이를 통해 안정적인 상태 관리 시스템을 구축할 수 있습니다.

더 자세한 정보는 MobX 공식 문서를 참고하세요.