모의 객체는 일부 프로그램 단위의 심층 행동 테스트를 수행 할 수있는 좋은 방법을 제공합니다. 테스트 된 유닛에 조롱 된 종속성을 전달하고 종속성이 제대로 작동하는지 확인해야합니다.유지 관리 가능한 머쉰
public class A
{
private B b;
public A(B b)
{
this.b = b;
}
public void DoSomething()
{
b.PerformSomeAction();
if(b.State == some special value)
{
b.PerformAnotherAction();
}
}
}
public class B
{
public BState State { get; private set; }
public void PerformSomeAction()
{
//some actions
State = some special value;
}
public void PerformAnotherAction()
{
if(State != some special value)
{
fail(); //for example throw new InvalidOperationException();
}
}
}
가 클래스 B는 단위 테스트를 TestB 테스트되고 상상 :
당신은이 클래스 A와 B를 보자.
단위 테스트 클래스 A에 B를 생성자에 전달하거나 (상태 기반 테스트 수행) B의 모의을 전달하여 (행동 기반 테스트 수행).
두 번째 접근법 (예 : A 상태를 직접 확인할 수없고 간접적으로 수행 할 수 없음)을 선택하고 UnitA 테스트 TestA (B에 대한 참조를 포함하지 않음)를 생성했다고 가정 해 보겠습니다.
그래서 우리는 인터페이스 IDependency을 소개하고 클래스가 다음과 같이 표시됩니다 확인
[TestClass]
public class TestB
{
[TestMethod]
public void ShouldPerformAnotherActionWhenDependencyReturnsSomeSpecialValue()
{
var d = CreateDependencyMockSuchThatItReturnsSomeSpecialValue();
var a = CreateA(d.Object);
a.DoSomething();
AssertSomeActionWasPerformedForDependency(d);
}
[TestMethod]
public void ShouldNotPerformAnotherActionWhenDependencyReturnsSomeNormalValue()
{
var d = CreateDependencyMockSuchThatItReturnsSomeNormalValue();
var a = CreateA(d.Object);
a.DoSomething();
AssertSomeActionWasNotPerformedForDependency(d);
}
}
:
public interface IDependency
{
void PerformSomeAction();
void PerformAnotherAction();
}
public class A
{
private IDependency d;
public A(IDependency d)
{
this.d = d;
}
public void DoSomething()
{
d.PerformSomeAction();
if(d.State == some special value)
{
d.PerformAnotherAction();
}
}
}
public class B : IDependency
{
public BState State { get; private set; }
public void PerformSomeAction()
{
//some actions
State = some special value;
}
public void PerformAnotherAction()
{
if(State != some special value)
{
fail(); //for example throw new InvalidOperationException();
}
}
}
및 단위 테스트를 TestB 비슷한입니다. 개발자에게 행복한 순간입니다. 모든 것이 테스트되고 모든 테스트는 녹색입니다. 모든 좋은.
하지만!
누군가가 클래스 B의 논리를 수정하면 (예 : (State! = some special value)에서 if (State! = 다른 값)로 수정) TestB 만 실패합니다.
이 사람은이 테스트를 수정하고 모든 것이 잘 돌아 간다고 생각합니다.
A의 생성자에 B를 전달하려고하면 A.DoSomething이 실패합니다.
근본 원인은 우리의 모의 객체입니다. B 객체의 이전 동작을 수정했습니다. B가 행동을 바꿨을 때 조롱에 반영되지 않았습니다.
내 질문은 B의 모의를 만드는 방법은 B의 동작 변경을 따르십니까?
귀하의 답변은 대부분 내가 생각하는 것과 내가 스스로 해결하고자하는 것입니다. Mocks가 인터페이스를 예외로 구현하는지 확인하는 일련의 테스트를 작성하는 것이 좋습니다. 좋은 습관입니까? 일부 유지 관리 문제가 있습니까? 우리는 단위 테스트 테스트 유틸리티 클래스도 필요합니다. 모의 동작을 수정하는 대신 단위 테스트 (각 인터페이스 구현에 대해 오버라이드되어야하는 추상적 인 기본 단위 테스트 클래스, 소위 계약 테스트)에서 수정해야합니다. 내가 맞습니까? – gerichhome