[英]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.