ユニットテストは、特定のユニットをテストすることです。したがって、クラス A の仕様を作成する場合、クラス A にクラス B および C の実際の具体的なバージョンがないことが理想的です。
後で、この質問のタグに C++ / Python が含まれていることに気付きましたが、原則は同じです。
public class A : InterfaceA
{
InterfaceB b;
InterfaceC c;
public A(InterfaceB b, InterfaceC c) {
this._b = b;
this._c = c; }
public string SomeOperation(string input)
{
return this._b.SomeOtherOperation(input)
+ this._c.EvenAnotherOperation(input);
}
}
上記のシステム A はシステム B と C にインターフェイスを挿入するため、実際の機能を他のシステムで実行することなく、システム A だけを単体テストできます。これは単体テストです。
以下は、動作の各部分に対して異なる When 仕様を使用して、作成から完成まで System にアプローチするための巧妙な方法です。
public class When_system_A_has_some_operation_called_with_valid_input : SystemASpecification
{
private string _actualString;
private string _expectedString;
private string _input;
private string _returnB;
private string _returnC;
[It]
public void Should_return_the_expected_string()
{
_actualString.Should().Be.EqualTo(this._expectedString);
}
public override void GivenThat()
{
var randomGenerator = new RandomGenerator();
this._input = randomGenerator.Generate<string>();
this._returnB = randomGenerator.Generate<string>();
this._returnC = randomGenerator.Generate<string>();
Dep<InterfaceB>().Stub(b => b.SomeOtherOperation(_input))
.Return(this._returnB);
Dep<InterfaceC>().Stub(c => c.EvenAnotherOperation(_input))
.Return(this._returnC);
this._expectedString = this._returnB + this._returnC;
}
public override void WhenIRun()
{
this._actualString = Sut.SomeOperation(this._input);
}
}
結論として、単一のユニット/仕様は複数の動作を持つことができ、仕様はユニット/システムを開発するにつれて成長します。また、テスト中のシステムがその中の他の具体的なシステムに依存している場合は注意してください。