[英]How to write Nunit test for a method which passes an object (C#)
[英]How write stub method with NUnit in C#
我有2節課:
SecondDeep.cs
我做了簡單的代碼,例如:
class FirstDeep
{
public FirstDeep() { }
public string AddA(string str)
{
SecondDeep sd = new SecondDeep();
bool flag = sd.SomethingToDo(str);
if (flag == true)
str = string.Concat(str, "AAA");
else
str = string.Concat(str, "BBB");
return str;
}
}
和
class SecondDeep
{
public bool SomethingToDo(string str)
{
bool flag = false;
if (str.Length < 10)
{
//todo something in DB, and after that flag should be TRUE
}
return flag;
}
}
然后,我想為方法“ AddA”編寫單元測試:
class Tests
{
[Test]
public void AddATest()
{
string expected = "ABCAAA";
FirstDeep fd = new FirstDeep();
string res = fd.AddA("ABC");
Assert.AreEqual(expected, res);
}
}
之后,我遇到了麻煩,我不知道在Test類中為方法SomethingToDo編寫正確的存根。 我總是有假的。 我應該返回TRUE。 但是如何?
允許您編寫存根的一個好方法是使用依賴注入 。 FirstDeep
取決於SecondDeep
,在測試中,您想用存根替換SecondDeep
。
首先通過提取用於SecondDeep
的接口來更改現有代碼,然后將其注入構造函數中的FirstDeep
中:
interface ISecondDeep {
Boolean SomethingToDo(String str);
}
class SecondDeep : ISecondDeep { ... }
class FirstDeep {
readonly ISecondDeep secondDeep;
public FirstDeep(ISecondDeep secondDeep) {
this.secondDeep = secondDeep;
}
public String AddA(String str) {
var flag = this.secondDeep.SomethingToDo(str);
...
}
}
請注意, FirstDeep
不再創建SecondDeep
實例。 而是將一個實例注入構造函數中。
在測試中,您可以為ISecondDeep
創建存根,其中SomethingToDo
始終返回true:
class SecondDeepStub : ISecondDeep {
public Boolean SomethingToDo(String str) {
return true;
}
}
在測試中,您使用存根:
var firstDeep = new FirstDeep(new SecondDeepStub());
在生產代碼中,使用“真實的” SecondDeep
:
var firstDeep = new FirstDeep(new SecondDeep());
使用依賴項注入容器和存根框架可以使很多操作變得更容易。
如果您不想重寫代碼,則可以使用諸如Microsoft Moles之類的框架來攔截調用。 在Visual Studio的下一版本中,類似的技術將在Fakes Framework中可用。
為了使您的代碼可測試,請不要在類內部實例化依賴關系。 使用依賴注入 (通過構造函數,屬性或參數)。 還可以使用抽象類或接口來模擬依賴項:
class FirstDeep
{
private ISecondDeep oa;
public FirstDeep(ISecondDeep oa)
{
this.oa = oa;
}
public string AddA(string str)
{
return String.Concat(str, oa.SomethingToDo(str) ? "AAA" : "BBB");
}
}
依賴於抽象允許您隔離測試類。
interface ISecondDeep
{
bool SomethingToDo(string str);
}
class SecondDeep : ISecondDeep
{
public bool SomethingToDo(string str)
{
bool flag = false;
if (str.Length < 10)
{
// without abstraction your test will require database
}
return flag;
}
}
這是測試樣本(使用Moq )。 它顯示了如何從調用返回true
到模擬的依賴項:
[TestFixture]
class Tests
{
[Test]
public void AddAAATest()
{
// Arrange
Mock<ISecondDeep> secondDeep = new Mock<ISecondDeep>();
secondDeep.Setup(x => x.SomethingToDo(It.IsAny<string>())).Returns(true);
// Act
FirstDeep fd = new FirstDeep(secondDeep.Object);
// Assert
Assert.That(fd.AddA("ABD"), Is.EqualTo("ABCAAA"));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.