[英]Unit test that legacy code reacts to ThreadAbortException in a certain way
我有一些遺留代碼,我想要進行測試。 這是必需品的復制品:
public class LegacyUnit
{
private readonly ICollaborator collaborator;
public LegacyUnit(ICollaborator collaborator)
{
this.collaborator = collaborator;
}
public object GetStuff(HttpContextBase context, string input)
{
try
{
if (input == "")
{
context.Response.End();
}
collaborator.DoOtherStuff();
return "Done!";
}
catch (ThreadAbortException)
{ }
return null;
}
}
現在,這個遺留單元存在一些問題,但是現在我只是試圖讓它受到考驗。 具體來說,我想測試一下,如果Response.End()
引發一個ThreadAbort
,則不會調用該collaborator.DoOtherStuff
。
問題:你如何提出這樣的例外?
我已經閱讀了這個問題及其在ThreadAbortException
答案 ,並了解它是特殊的。 但是,我從這些帖子中看不到如何在單元測試中處理這個問題。
這是我的嘗試:
[Test]
public void DoesNotCallCollaboratorOnThreadAbort()
{
var testResponseMock = new Mock<HttpResponseBase>();
var testContextMock = new Mock<HttpContextBase>();
var collaboratorMock = new Mock<ICollaborator>();
testContextMock.Setup(x => x.Response).Returns(testResponseMock.Object);
testResponseMock.Setup(x => x.End()).Throws<ThreadAbortException>(); // Compile error
var unit = new LegacyUnit(collaboratorMock.Object);
unit.GetStuff(testContextMock.Object, "");
collaboratorMock.Verify(c => c.DoOtherStuff(), Times.Never);
}
顯然編譯器抱怨: ThreadAbortException
沒有可用的構造函數。 此外,它是sealed
(可能有充分的理由),因此創建一個“可測試的”子類是行不通的。
獲得此類代碼的正確方法是什么? 它甚至是可行的,還是LegacyUnit
對測試不友好?
完整,最小的repro(帶有NUnit 2.6.4和Moq 4.5.9的空.NET 4.5類庫):
public interface ICollaborator
{
void DoOtherStuff();
}
public class LegacyUnit
{
private readonly ICollaborator collaborator;
public LegacyUnit(ICollaborator collaborator)
{
this.collaborator = collaborator;
}
public object GetStuff(HttpContextBase context, string input)
{
try
{
if (input == "") context.Response.End();
collaborator.DoOtherStuff();
return "Done!";
}
catch (ThreadAbortException)
{ }
return null;
}
}
[TestFixture]
public class LegacyUnitTests
{
[Test]
public void DoesNotCallCollaboratorOnThreadAbort()
{
var testResponseMock = new Mock<HttpResponseBase>();
var testContextMock = new Mock<HttpContextBase>();
var collaboratorMock = new Mock<ICollaborator>();
testContextMock.Setup(x => x.Response).Returns(testResponseMock.Object);
testResponseMock.Setup(x => x.End()).Throws<ThreadAbortException>(); // Compile error here
var unit = new LegacyUnit(collaboratorMock.Object);
unit.GetStuff(testContextMock.Object, "");
collaboratorMock.Verify(c => c.DoOtherStuff(), Times.Never);
}
}
通過在其上調用Abort
在目標線程中引發ThreadAbortException
。 您可以創建一個線程來運行測試,並在模擬testResponseMock.End
調用Abort
,例如
testContextMock.Setup(x => x.Response).Returns(testResponseMock.Object);
var unit = new LegacyUnit(collaboratorMock.Object);
var thread = new Thread(() => unit.GetStuff(testContextMock.Object, ""));
testResponseMock.Setup(x => x.End()).Callback(() => { Thread.CurrentThread.Abort(); });
thread.Start();
thread.Join();
collaboratorMock.Verify(c => c.DoOtherStuff(), Times.Never);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.