私は最近、同じクラス内のメソッドから同じクラス内のメソッドへの結果または呼び出しをスタブするのに最適な次の2つのメソッドを友人と話していました。
これは非常に単純化された例です。実際には、機能ははるかに複雑です。
例:
public class MyClass
{
public bool FunctionA()
{
return FunctionB() % 2 == 0;
}
protected int FunctionB()
{
return new Random().Next();
}
}
これをテストするために、2つのメソッドがあります。
方法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
boolを返しますが、ローカル変数のみを設定し、x
何も返しません。