[unit-testing] mock 객체의 목적은 무엇입니까?


Answers

모의 객체는 실제 객체를 대체하는 객체입니다. 객체 지향 프로그래밍에서 모의 ​​객체는 제어 된 방식으로 실제 객체의 동작을 모방 한 시뮬레이션 객체입니다.

컴퓨터 프로그래머는 일반적으로 자동차 설계자가 차량 충격에서 인간의 동적 거동을 시뮬레이트하기 위해 충돌 테스트 더미를 사용하는 것과 같은 방식으로 다른 객체의 동작을 테스트하기위한 모의 객체를 만듭니다.

http://en.wikipedia.org/wiki/Mock_object

Mock 객체를 사용하면 데이터베이스와 같이 크고 다루기 힘든 리소스를 가져 오지 않고도 테스트 시나리오를 설정할 수 있습니다. 테스트를 위해 데이터베이스를 호출하는 대신 단위 테스트에서 모의 ​​객체를 사용하여 데이터베이스를 시뮬레이션 할 수 있습니다. 이렇게하면 실제 데이터베이스를 설정하고 해체해야하는 부담으로부터 해방되어 클래스의 단일 메소드를 테스트 할 수 있습니다.

"모의 (Mock)"라는 단어는 때때로 "스텁 (Stub)"과 같은 의미로 사용됩니다. 두 단어의 차이점은 여기설명되어 있습니다. 근본적으로 모의 객체는 테스트 대상 객체 / 메소드의 적절한 동작에 대한 기대치 (예 : "단정")도 포함하는 스텁 객체입니다.

예 :

class OrderInteractionTester...
  public void testOrderSendsMailIfUnfilled() {
    Order order = new Order(TALISKER, 51);
    Mock warehouse = mock(Warehouse.class);
    Mock mailer = mock(MailService.class);
    order.setMailer((MailService) mailer.proxy());

    mailer.expects(once()).method("send");
    warehouse.expects(once()).method("hasInventory")
      .withAnyArguments()
      .will(returnValue(false));

    order.fill((Warehouse) warehouse.proxy());
  }
}

warehousemailer 모의 객체는 예상 결과와 함께 프로그래밍됩니다.

Question

나는 단위 테스트를 처음 접했고, 계속해서 많은 것을 던진 '모의 물건'이라는 말을 듣는다. 평신도의 관점에서, 누군가 가짜 객체가 무엇인지, 그리고 단위 테스트를 작성할 때 전형적으로 사용되는 것을 설명 할 수 있습니까?




php와 phpunit에 대해서는 phpunit 문서에서 잘 설명되어 있습니다. phpunit 문서를 보시려면 여기를 클릭하십시오

간단한 단어 조롱 (mocking) 객체는 원래 객체의 더미 객체이며 반환 값을 반환합니다.이 반환 값은 테스트 클래스에서 사용될 수 있습니다.




또 다른 대답은 " Mocks Are Stubs "링크를 통해 제안 되었 듯이, mock은 실제 객체 대신 사용할 "test double"의 한 형태입니다. 스텁 객체와 같은 다른 유형의 테스트 복식과 다른 점은 다른 테스트 복식이 상태 확인 (및 선택적으로 시뮬레이션)을 제공하는 반면 모의는 동작 확인 (및 선택적으로 시뮬레이션)을 제공한다는 것입니다.

스텁을 사용하면 스텁에서 여러 가지 메서드를 임의의 순서로 (또는 보잘것없이) 호출하고 스텁이 의도 한 값이나 상태를 캡처 한 경우 성공 여부를 결정할 수 있습니다. 대조적으로, mock 객체는 매우 특정한 함수가 특정 순서로, 심지어는 특정 횟수만큼 호출 될 것으로 기대합니다. mock 객체가있는 테스트는 테스트가 끝났을 때 mock 객체가 올바른 상태 였더라도 메소드가 다른 시퀀스 또는 카운트에서 호출 되었기 때문에 단순히 "실패한"것으로 간주됩니다!

이런 방식으로, 모의 객체는 종종 스텁 객체보다 SUT 코드에 더 밀접하게 결합 된 것으로 간주됩니다. 그것은 당신이 무엇을 증명하려고하는지에 따라 좋거나 나쁠 수 있습니다.




컴퓨터 프로그램의 일부분을 단위 테스트 할 때 특정 부분의 동작 만 테스트하려는 것이 이상적입니다.

예를 들어 다른 프로그램을 사용하여 인쇄물을 호출하는 프로그램의 가상 코드에서 아래의 의사 코드를 살펴보십시오.

If theUserIsFred then
    Call Printer(HelloFred)
Else
   Call Printer(YouAreNotFred)
End

이것을 테스트했다면, 사용자가 Fred인지 아닌지 살펴 보는 부분을 주로 테스트하고 싶을 것입니다. 당신은 실제로 사물의 Printer 부분을 ​​테스트하고 싶지 않습니다. 그것은 또 다른 시험이 될 것입니다.

이것은 모의 객체가 들어오는 곳입니다. 그들은 다른 유형의 물건 인 척합니다. 이 경우 모의 Printer 사용하면 실제 프린터처럼 작동하지만 인쇄와 같이 불편한 일은하지 않을 것입니다.

Mock이 아닌 다른 유형의 척척 물건을 사용할 수 있습니다. 모의 가짜를 만드는 주된 이유는 행동과 기대치로 구성 될 수 있다는 것입니다.

Mock을 잘못 사용하면 Mock에서 오류가 발생할 수 있습니다. 따라서 위의 예에서는 "user is Fred"테스트 케이스에서 HelloFred를 사용하여 프린터를 호출 할 수 있습니다. 그렇게하지 않으면 당신의 모의에서 경고 할 수 있습니다.

Mocks의 동작은 예를 들어 코드에서 다음과 같은 것을 수행했다는 것을 의미합니다.

If Call Printer(HelloFred) Returned SaidHello Then
    Do Something
End

이제 Printer가 호출되어 SaidHello를 반환 할 때 코드가하는 일을 테스트하기를 원합니다. HelloFred를 호출 할 때 SaidHello를 반환하도록 Mock을 설정할 수 있습니다.

이 문제를 해결하는 좋은 방법은 Martin Fowlers가 Mocks are Stubs입니다.




Mock 객체는 Test Double 의 한 종류입니다. mockobjects를 사용하여 테스트중인 클래스와 다른 클래스 간의 상호 작용을 테스트하고 확인합니다.

일반적으로 여러분은 여러분의 클래스가 기본 객체에 대해 수행 할 것으로 기대하는 메소드 호출에 대해 '프로그램'또는 '기록'기대치를 제공합니다.

예를 들어 위젯의 필드를 업데이트하는 서비스 메소드를 테스트한다고 가정 해 보겠습니다. 그리고 당신의 아키텍쳐에는 데이터베이스를 다루는 WidgetDAO가 있습니다. 데이터베이스에 대해 이야기하는 것이 느리며 설정 및 관리가 복잡하기 때문에 WidgetDao를 조롱합니다.

서비스가 무엇을해야하는지 생각해 봅시다. 데이터베이스에서 위젯을 가져와 함께 처리하고 다시 저장해야합니다.

그러므로 가상 모의 라이브러리를 가진 의사 언어에서 우리는 다음과 같은 것을 가질 것입니다 :

Widget sampleWidget = new Widget();
WidgetDao mock = createMock(WidgetDao.class);
WidgetService svc = new WidgetService(mock);

// record expected calls on the dao
expect(mock.getById(id)).andReturn(sampleWidget);   
expect(mock.save(sampleWidget);

// turn the dao in replay mode
replay(mock);

svc.updateWidgetPrice(id,newPrice);

verify(mock);    // verify the expected calls were made
assertEquals(newPrice,sampleWidget.getPrice());

이 방법으로 다른 클래스에 의존하는 클래스의 드라이브 개발을 쉽게 테스트 할 수 있습니다.




Links