更新:我改變了這個問題的措辭。以前,如果在運行時可以更改基類,那麼是/否問題。如何在C#中的單元測試時間模擬/僞造/替換/存根基類?
我可能在這裏不可能完成任務,但我似乎正在接近。我想擴展一個ASP.NET控件,並且我希望我的代碼是單元可測試的。另外,我希望能夠僞造真正Label的行爲(即ID生成等),這是真正的Label在nUnit主機中無法做到的。
這裏有一個工作示例,它對依賴於真實基類的東西進行斷言,而不是在更真實的單元測試中,測試將依賴於--i.e。存在的ID和一些自定義行爲。
總之代碼表示,它比我好的人:
public class LabelWrapper : Label //Runtime
//public class LabelWrapper : FakeLabel //Unit Test time
{
private readonly LabelLogic logic= new LabelLogic();
public override string Text
{
get
{
return logic.ProcessGetText(base.Text);
}
set
{
base.Text=logic.ProcessSetText(value);
}
}
}
//Ugh, now I have to test FakeLabelWrapper
public class FakeLabelWrapper : FakeLabel //Unit Test time
{
private readonly LabelLogic logic= new LabelLogic();
public override string Text
{
get
{
return logic.ProcessGetText(base.Text);
}
set
{
base.Text=logic.ProcessSetText(value);
}
}
}
[TestFixture]
public class UnitTest
{
[Test]
public void Test()
{
//Wish this was LabelWrapper label = new LabelWrapper(new FakeBase())
LabelWrapper label = new LabelWrapper();
//FakeLabelWrapper label = new FakeLabelWrapper();
label.Text = "ToUpper";
Assert.AreEqual("TOUPPER",label.Text);
StringWriter stringWriter = new StringWriter();
HtmlTextWriter writer = new HtmlTextWriter(stringWriter);
label.RenderControl(writer);
Assert.AreEqual(1,label.ID);
Assert.AreEqual("<span>TOUPPER</span>", stringWriter.ToString());
}
}
public class FakeLabel
{
virtual public string Text { get; set; }
public void RenderControl(TextWriter writer)
{
writer.Write("<span>" + Text + "</span>");
}
}
//System Under Test
internal class LabelLogic
{
internal string ProcessGetText(string value)
{
return value.ToUpper();
}
internal string ProcessSetText(string value)
{
return value.ToUpper();
}
}
我同意你的看法,在運行時沒有辦法改變基類。我仍然希望找到模式來模擬它。但是,我不確定(如果可能的話),這與返回具有相同基類或支持相同接口的替代實現的工廠有什麼不同。工廠可能會選擇惡意實施或無效實施。 – MatthewMartin 2010-03-23 20:55:27