[英]Can you unit test a void method which doesnt have return type?
我有這個無效的方法,我想進行單元測試,但是不幸的是,我對此沒有太多的經驗。
public void findOccuranceMethod()
{
string str = "The Haunting of Hill House!";
Console.WriteLine("String: " + str);
string occurString = "o";
string replaceString = "MDDS";
var array = str.Split(new[] { occurString }, StringSplitOptions.None);
var count = array.Length - 1;
string result = string.Join(replaceString, array);
Console.WriteLine("String after replacing a character: " + result);
Console.WriteLine("Number of replaces made: " + count);
Console.ReadLine();
}
這是我要測試的TestClass,但運行時它會不斷加載:
[TestMethod()]
public void findOccuranceMethodTest()
{
// Arrange
string expected = "The Haunting MDDSf Hill HMDDSuse!";
// Act
var result = new findOccurance();
// Assert
Assert.AreEqual(expected, result);
}
對這種邏輯進行編碼和單元測試的正確方法是:
public class SomeProductionClass
{
public string findOccuranceMethod(string str)
{
string occurString = "o";
string replaceString = "MDDS";
var array = str.Split(new[] { occurString }, StringSplitOptions.None);
string result = string.Join(replaceString, array);
return result;
}
}
[TestMethod()]
public void findOccuranceMethodTest()
{
// Arrange
string expected = "The Haunting MDDSf Hill HMDDSuse!";
var productionClass = new SomeProductionClass();
// Act
var result = productionClass.findOccuranceMethod("The Haunting of Hill House!");
// Assert
Assert.AreEqual(expected, result);
}
如果由於某種原因您無法控制生產代碼,則有兩個選擇:
用抽象替換Console
將標准輸入/輸出重新分配給自定義流:這是最不推薦使用的選項,因為它會使設置/清除更加復雜,並且可能會干擾測試運行程序。
無論哪種情況,我們都決不能以會為測試/生產引入單獨分支的方式修改被測代碼。 例如,“如果在測試中運行,則執行A,否則執行B” –在這種情況下,我們實際上不是在測試生產代碼,而是測試它的另一個分支。
在這里,我們介紹IConsole
替代System.Console
:
public interface IConsole
{
void WriteLine(string s);
void ReadLine(); // void is enough for this example
}
// for use in production
public class RealConsole : IConsole
{
public void WriteLine(string s)
{
Console.WriteLine(s);
}
public void ReadLine()
{
Console.ReadLine();
}
}
// for use in unit tests
public class TestConsole : IConsole
{
public void WriteLine(string s)
{
Contents.Add(s);
}
public void ReadLine()
{
}
public List<string> Contents { get; } = new List<string>();
}
生產代碼將保留原始帖子中的內容,只不過現在它使用_console
作為依賴項:
public class SomeProductionClass
{
private readonly IConsole _console;
public SomeProductionClass(IConsole console)
{
_console = console;
}
public void findOccuranceMethod()
{
string str = "The Haunting of Hill House!";
_console.WriteLine("String: " + str);
string occurString = "o";
string replaceString = "MDDS";
var array = str.Split(new[] { occurString }, StringSplitOptions.None);
var count = array.Length - 1;
string result = string.Join(replaceString, array);
_console.WriteLine("String after replacing a character: " + result);
_console.WriteLine("Number of replaces made: " + count);
_console.ReadLine();
}
}
測試代碼為:
[TestMethod()]
public void findOccuranceMethodTest()
{
// Arrange
string expectedString = "The Haunting MDDSf Hill HMDDSuse!";
int expectedCount = 2;
var console = new TestConsole();
var productionClass = new SomeProductionClass(console);
// Act
productionClass.findOccuranceMethod();
// Assert
Assert.AreEqual(3, console.Contents.Count);
Assert.AreEqual("String: The Haunting of Hill House!", console.Contents[0]);
Assert.AreEqual(
$"String after replacing a character: {expectedString}",
console.Contents[1]);
Assert.AreEqual(
$"Number of replaces made: {expectedCount}",
console.Contents[2]);
}
如果需要保留簽名,可以使用可選參數:
public void optionSameSignature(Action<string> log = null, Func<string> read = null)
{
log = log ?? Console.WriteLine;
read = read ?? Console.ReadLine;
string str = "The Haunting of Hill House!";
log("String: " + str);
string occurString = "o";
string replaceString = "MDDS";
var array = str.Split(new[] { occurString }, StringSplitOptions.None);
var count = array.Length - 1;
string result = string.Join(replaceString, array);
log("String after replacing a character: " + result);
log("Number of replaces made: " + count);
read();
}
public void Test()
{
List<string> lines = new List<string>();
optionSameSignature(lines.Add, () => "");
}
從更深層次上講,輸入和輸出是技術細節,因此理想情況下,您將嘗試使用沒有技術細節的業務價值代碼。 這樣的事情可能更接近您的實際需求:
private static void mybusinessfunction(string input, out int count, out string result)
{
string occurString = "o";
string replaceString = "MDDS";
var array = input.Split(new[] { occurString }, StringSplitOptions.None);
count = array.Length - 1;
result = string.Join(replaceString, array);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.