這裏的假設是personRepo
被注入到被測主題中。因此我也假設你正在使用DI。
當前顯示的代碼與靜態實現問題緊密耦合,這使得難以單獨測試主題。
爲了使主題更加靈活,更易於維護和隔離測試,主題需要重構以取決於抽象而不是結核。
在抽象背後封裝靜態LogHelper
。
public interface ILogger {
void LogDebug(string category, string msg);
//...other members
}
這將包裝所需的行爲/功能
public class LogHelperWrapper : ILogger {
public void LogDebug(string source, string msg) {
LogHelper.LogDebug(source, msg);
}
//...other members
}
主題會利用抽象,這將重構通過構造注射遵循顯式依賴的原則。
private ILogger log; //set via constructor injection
try {
person = this.personRepo.GetPerson(name);
} catch (PersonException) {
this.log.LogDebug("PersonService", "No Person found!");
}
這將允許被測試者在隔離測試時接收替換物。
//Arrange
var logger = A.Fake<ILogger>();
//...other arrangements
//Act
//...exercise test
//Assertion
A.CallTo(() => logger.LogDebug("PersonService", "No Person found!"))
.MustHaveHappened(Repeated.Exactly.Once);
//...other assertions.
因爲'LogHelper.LogDebug'是靜態方法 - 你不能嘲笑它。所以你需要測試'LogDebug'的實際行爲。如果它寫入文件 - 讀取文件,如果寫入數據庫 - 讀取數據庫。如果'LogHelper'可配置 - 您可以將其配置爲可以輕鬆測試的輸出(例如MemoryStream)。但是潔具,它是靜態方法,如果你並行運行測試 - 其他測試會受到相同配置的影響。適當的可測試解決方案 - 引入「記錄器」的抽象並將其注入課堂。實際的實現仍然可以調用靜態方法。 – Fabio
這通常很複雜。這也是避免靜力學的一個原因。您可以使用MS Fakes(Shim Types),但AFAIK您需要Visual Studio Enterprise(或以前的最終版本)。否則,您可能會應用重構。如果依賴注入不是您的選擇,那麼您可以首先引入一個單例LogHelper.Instance.LogDebug(...),它可以在單元測試中設置。 – Peit
如果發生異常,您可以嘗試測試。但在測試結束時,您應該刪除已保存的數據。不知道這是否是最好的方法。 – Sasha