在自定义 NancyFx 引导程序中测试代码

Testing code in a custom NancyFx Bootstrapper

我有一个使用 StructureMapNancyBootstrapper 的自定义 Nancy Bootstrapper,但无论容器如何,问题都是一样的。

public class CustomNancyBootstrapper : StructureMapNancyBootstrapper
{
    protected override void RequestStartup(IContainer container, IPipelines pipelines, NancyContext context)
    {
        var auth = container.GetInstance<ICustomAuth>();
        auth.Authenticate(context);
    }
}

我想编写一个测试来断言使用上下文调用了 Authenticate...类似这样...

[Test]
public void RequestStartup_Calls_CustomAuth_Authenticate_WithContext()
{
    // set up
    var mockAuthentication = new Mock<ICustomAuth>();
    var mockContainer = new Mock<IContainer>();
    var mockPipelines = new Mock<IPipelines>();
    var context = new NancyContext();

    mockContainer.Setup(x => x.GetInstance<ICustomAuth>()).Returns(mockAuthentication.Object);

    // exercise
    _bootstrapper.RequestStartup(_mockContainer.Object, _mockPipelines.Object, context);

    // verify
    mockAuthentication.Verify(x => x.Authenticate(context), Times.Once);
}

问题是我无法调用 RequestStartup,因为它受到 NancyBootstrapperBase 中定义的保护。

protected virtual void RequestStartup(TContainer container, IPipelines pipelines, NancyContext context);  

有没有一种 "proper"/"offical" Nancy 方法可以在不创建另一个派生 class 并公开这些方法的情况下执行此操作,因为这看起来像是 hack?

谢谢

我想你可以 "fake" 使用 Browser from Nancy.Testing:

请求
 var browser = new Browser(new CustomNancyBootstrapper());

 var response = browser.Get("/whatever");

有一组很好的关于测试 NancyFx 应用程序的文章: http://www.marcusoft.net/2013/01/NancyTesting1.html

原来 Nancy 提供了一个 IRequetStartup 接口,因此您可以从自定义引导程序中取出代码并执行类似这样的操作...

public class MyRequestStart : IRequestStartup
{
    private readonly ICustomAuth _customAuthentication;

    public MyRequestStart(ICustomAuth customAuthentication)
    {
        if (customAuthentication == null)
        {
            throw new ArgumentNullException(nameof(customAuthentication));
        }

        _customAuthentication = customAuthentication; 
    }

    public void Initialize(IPipelines pipelines, NancyContext context)
    {
        _customAuthentication.Authenticate(context);
    }
}

测试简单明了

    [Test]
    public void When_Initialize_Calls_CustomAuth_Authenticate_WithContext()
    {
        // set up 
        var mockAuth = new Mock<ICustomAuth>();
        var requestStartup = new MyRequestStart(mockAuth.Object);
        var mockPipeline = new Mock<IPipelines>();
        var context = new NancyContext();

        // exercise
        requestStartup.Initialize(mockPipeline.Object, context);

        // verify
        mockAuth.Verify(x => x.Authenticate(context), Times.Once);
    }

https://github.com/NancyFx/Nancy/wiki/The-Application-Before%2C-After-and-OnError-pipelines#implementing-interfaces