Moq context.server.transfer

时间:2012-02-29 11:49:42

标签: moq mstest

对于单元测试,我使用moq来模拟附加到HttpContextBase的HttpServerUtilityBase。这样当被测函数可以调用context.server(ASP.Net)。

但是,当测试的方法执行context.server.transfer时,在应用程序中完成时,这会导致函数(在httphandler中调用)停止执行。在我的moq'd版本中,执行“传输”调用,然后继续执行。

为了解决这个问题,我在转移后放置了返回语句,但是这些语句被stylecop正确识别为多余。

我可以设置我的Mock来强制调用方法返回吗?

例如,如果我们正在测试这样的方法:

public void ProcessRequest(HttpContextBase context, string username, Logger logger)
{
    if (string.isNullOrEmpty(username))
    {
        logger.Warn("Blah Blah invalid username");
        context.Server.Transfer("~/ErrorPage.aspx");
    }
    ETC...
}

以下代码将正确测试对无效用户名采取的正确操作。

[TestMethod]
public void ProcessRequestTest()
{
    // Set up my mocks
    var logger = new Mock<ILogger>();
    logger.Setup(l => l.Warn(It.IsAny<string>());
    var context = new Mock<HttpContextBase>();
    var server = new Mock<HttpServerUtilityBase>();
    context.Setup(c => c.Server).Returns(server.Object);

    // Try an invalid call
    var rh = new MyRequestHandler();
    rh.ProcessRequest(context.Object, string.empty, logger.Object);

    // Check that the message was logged and the transfer was made
    logger.Verify(l => l.Warn(It.IsRegex("invalid username"));
    server.Verify(s => s.Transfer(It.IsAny<string>()));
}

但是因为context.Server被模拟,所以Transfer不会停止执行ProcessRequest,除非我在传输后放入一个返回,否则测试将通过“ETC ...”块执行。

1 个答案:

答案 0 :(得分:1)

这非常棘手,这就是为什么通常不建议模拟您不拥有的对象。一种解决方案是抛出异常(我认为它是如何在ASP.NET代码中完成的)。有关“重定向后停止执行”一节下的示例,请参阅此link

类似于:

server.Setup(s => s.Transfer(It.IsAny<string>()).Throws<TransferException>();

然后用NUnit的Assert.Throws捕获它。