[英]Mocking a StreamWriter/determining when to mock
我有一個使用StreamWriter寫入文件的類。
public void CreateLog(string errorLogFilePath, StringBuilder errorLogBuilder, string errorMessage)
{
using (StreamWriter sw = new StreamWriter(errorLogFilePath, true)
{
errorLogBuilder.Apend("An error was discovered.");
//....
sw.Write(errorLogBuilder.ToString());
}
}
[問題]
1:可以檢查是否調用了.Write()方法嗎?
2:是否需要在不實際訪問硬盤驅動器的情況下將MemoryStream包裝在StreamWriter內以便對其進行測試。 StreamWriters構造函數之一接受一個流,但是它聲明以下+ UTF-8編碼會對此產生影響嗎?
使用UTF-8編碼和默認緩沖區大小為指定的流初始化StreamWriter類的新實例。
3:如何確定某個班級是否實際上正在訪問高清並因此需要模擬? (對不起,如果最后一個問題聽起來很愚蠢,但對此我真的感到有點困惑。)
讓該方法寫入TextWriter而不是StreamWriter。 然后通過將其傳遞給模擬TextWriter來測試該方法。 當然,在“真實”代碼中,您將傳入使用new StreamWriter(errorLogFilePath, true)
創建的new StreamWriter(errorLogFilePath, true)
。
這將為您的問題提供以下答案:
更多細節:
將方法重構為兩種方法:
public void CreateLog(string errorLogFilePath, StringBuilder errorLogBuilder, string errorMessage)
{
using (StreamWriter sw = new StreamWriter(errorLogFilePath, true)
{
CreateLog(sw, errorLogBuilder, errorMessage);
}
}
public void CreateLog(TextWriter writer, StringBuilder errorLogBuilder, string errorMessage)
{
errorLogBuilder.Apend("An error was discovered.");
//....
writer.Write(errorLogBuilder.ToString());
}
測試第一個方法,以確保它使用適當構造的StreamWriter調用第二個方法。 測試第二個方法,以確保它使用適當的參數在傳遞的TextWriter上調用Write
。 現在,您已經抽象了對硬盤驅動器的依賴性。 您的測試未使用硬盤驅動器,但您正在測試所有內容。
一般來說,您可以:
使用經過良好測試的日志庫(例如NLog,MS Logging Application Block),可以避免開發和維護自己的日志庫。
通過其接口將日志記錄邏輯(或調用消息框,打開文件對話框等的代碼)重構為服務。 這樣,您可以拆分測試策略:
IE瀏覽器:
// arrrange
File.Delete("bar.log")
// act
CreateLog("bar.log", errorLogBuilder, "FOO")
// assert
Assert.IsTrue( File.Exists("bar.log") )
Assert.IsTrue( File.ReadAllLines("bar.log").First() == "FOO")
關鍵是要確保通過模擬來調用該組件。 然后,您可以檢查組件是否按預期工作。
我知道這是一個非常老的問題,但在嘗試解決類似問題時遇到了這個問題,即如何偽造StreamWriter。
我解決此問題的方法是,沒有在using語句的一部分內在方法內部創建StreamWriter,而是在ctor內預先創建(使您的類從IDisposable擴展,然后在Dispose方法中銷毀StreamWriter)。 然后在測試過程中在其頂部注入偽造品:
internal class FakeStreamWriter : StreamWriter
{
public List<string> Writes { get; set; } = new List<string>();
public FakeStreamWriter() : base(new MemoryStream()) { }
public override void Write(string value)
{
WriteLine(value);
}
public override void WriteLine(string value)
{
Writes.Add(value);
}
public override void Flush()
{
}
}
我的單元測試方法如下所示:
public void SmtpStream_Negotiate_EhloResultsCorrectly()
{
var ctx = new APIContext();
var logger = new FakeLogger();
var writer = new FakeStreamWriter();
var reader = new FakeStreamReader { Line = "EHLO test.com" };
var stream = new SmtpStream(logger, ctx, new MemoryStream())
{
_writer = writer,
_reader = reader
};
Exception ex = null;
try
{
stream.Negotiate(ctx);
}
catch (Exception x)
{
ex = x;
}
Assert.IsNull(ex);
Assert.IsTrue(writer.Writes.ElementAt(0) == "250 Hello test.com");
Assert.IsTrue(writer.Writes.ElementAt(1) == "250 STARTTLS");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.