我會冒昧地使用NSubstitute而不是moq,但是你可以想想如何用moq來做到這一點。我也會使用AutoFixture.Xunit2,因爲它很棒。
private MainClass _target;
private IFoo _foo = Substitue.For<IFoo>();
private IBar _bar = Substitute.For<IBar>();
private IBaz _baz = Substitute.For<IBaz>();
public MainClassTest()
{
_target = new MainClass(_foo, _bar, _baz);
}
[Theory, AutoData]
public void DoStuff_Delegates_To_Foo(string myParam)
{
_target.DoStuff(myParam);
_foo.Received.DoFoo(Arg.Is(myParam));
}
[Theory, AutoData]
public void DoStuff_Calls_Bar_With_Result_From_Foo(string myParam, object fooResult)
{
_foo.DoFoo(Arg.Is(myParam)).Returns(fooResult);
_target.DoStuff(myParam);
_bar.Received().DoBar(Arg.Is(fooResult));
}
[Theory, AutoData]
public void DoStuff_Calls_Baz_After_Foo_And_Bar(string myParam)
{
_target.DoStuff(myParam);
Received.InOrder(() =>
{
_foo.DoFoo(Arg.Any<string>());
_bar.DoBar(Arg.Any<object>());
_baz.DoBaz();
}
}
的想法是有你想知道的DoStuff
方法每一件事情的測試方法。以上僅爲示例,如果您想要,您也可以在一次測試中將其全部寫完。這裏面臨的挑戰是對測試內容進行很好的描述(所以想象一下你命名測試,並且你的同事實現它),無論如何,這裏有一個嚴格命名的測試方法的例子,它測試了一切。
[Theory, AutoData]
public void DoStuff_Does_What_It_Is_Supposed_To_Do(string myParam, object fooResult)
{
_foo.DoFoo(Arg.Is(myParam)).Returns(fooResult);
_target.DoStuff(myParam);
Received.InOrder(() =>
{
_foo.DoFoo(Arg.Is(myParam));
_bar.DoBar(Arg.Is(fooResult));
_baz.DoBaz();
}
}
所以要回答你的問題,它歸結爲命名。如果你能用一個簡短的句子來描述這個測試,那就繼續做吧。你可能聽說每種測試方法都應該測試一件事情,而且只測試一件事情,如果你在這個上下文中把「事物」想象成你可以用一個簡短的句子來描述的東西,它會有所幫助。
單元測試什麼?反對什麼規格?我在這裏看不到界面。 – Raedwald
IFoo是測試DoStuff時會被模擬的接口之一。 – eych