나는 최근에 어떤 친구들과 다음 두 가지 방법 중 어느 것이 같은 클래스 내부의 메소드에서 같은 클래스 내의 메소드에 대한 반환 결과 또는 호출을 스텁하는 것이 가장 좋은지에 대해 이야기했습니다.
이것은 매우 간단한 예입니다. 실제로 기능은 훨씬 더 복잡합니다.
예:
public class MyClass
{
public bool FunctionA()
{
return FunctionB() % 2 == 0;
}
protected int FunctionB()
{
return new Random().Next();
}
}
이를 테스트하기 위해 두 가지 방법이 있습니다.
방법 1 : 기능 및 동작을 사용하여 방법의 기능을 대체하십시오. 예:
public class MyClass
{
public Func<int> FunctionB { get; set; }
public MyClass()
{
FunctionB = FunctionBImpl;
}
public bool FunctionA()
{
return FunctionB() % 2 == 0;
}
protected int FunctionBImpl()
{
return new Random().Next();
}
}
[TestClass]
public class MyClassTests
{
private MyClass _subject;
[TestInitialize]
public void Initialize()
{
_subject = new MyClass();
}
[TestMethod]
public void FunctionA_WhenNumberIsOdd_ReturnsTrue()
{
_subject.FunctionB = () => 1;
var result = _subject.FunctionA();
Assert.IsFalse(result);
}
}
방법 2 : 멤버를 가상으로, 클래스 파생 및 파생 클래스에서 함수 및 작업을 사용하여 기능 대체
public class MyClass
{
public bool FunctionA()
{
return FunctionB() % 2 == 0;
}
protected virtual int FunctionB()
{
return new Random().Next();
}
}
public class TestableMyClass
{
public Func<int> FunctionBFunc { get; set; }
public MyClass()
{
FunctionBFunc = base.FunctionB;
}
protected override int FunctionB()
{
return FunctionBFunc();
}
}
[TestClass]
public class MyClassTests
{
private TestableMyClass _subject;
[TestInitialize]
public void Initialize()
{
_subject = new TestableMyClass();
}
[TestMethod]
public void FunctionA_WhenNumberIsOdd_ReturnsTrue()
{
_subject.FunctionBFunc = () => 1;
var result = _subject.FunctionA();
Assert.IsFalse(result);
}
}
나는 왜 더 나은지 알고 싶어?
업데이트 : 참고 : FunctionB도 공개 가능
FunctionB
디자인에 의해 깨졌습니다. new Random().Next()
거의 항상 잘못되었습니다. 의 인스턴스를 주입해야합니다 Random
. ( Random
또한 잘못 설계된 클래스이므로 몇 가지 추가 문제가 발생할 수 있습니다.)
FunctionA
부울을 반환하지만 로컬 변수 만 설정하고x
아무것도 반환하지 않습니다.