我试图测试从我的Nancy应用程序返回的模型是否符合预期。我已按照文档here进行了操作,但每当我调用GetModel<T>
扩展方法时,它都会抛出KeyNotFoundException
。
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
我知道这个错误意味着什么,但我没有理解为什么会被抛出。
这是我的模块
public class SanityModule : NancyModule
{
public SanityModule()
{
Get["sanity-check"] = _ => Negotiate.WithModel(new SanityViewModel { Id = 1 })
.WithStatusCode(HttpStatusCode.OK);
}
}
我的观点模型
public class SanityViewModel
{
public int Id { get; set; }
}
这是我的考试
[TestFixture]
public class SanityModuleTests
{
[Test]
public void Sanity_Check()
{
// Arrange
var browser = new Browser(with =>
{
with.Module<SanityModule>();
with.ViewFactory<TestingViewFactory>();
});
// Act
var result = browser.Get("/sanity-check", with =>
{
with.HttpRequest();
with.Header("accept", "application/json");
});
var model = result.GetModel<SanityViewModel>();
// Asset
model.Id.ShouldBeEquivalentTo(1);
}
}
调试此测试表明模块已命中并完成正常。运行应用程序会显示响应符合预期。
任何人都可以对此有所了解吗?
答案 0 :(得分:3)
感谢可爱的家伙albertjan和the.fringe.ninja,在Nancy Jabbr room我们已经解释了这里发生了什么。
TL; DR 这是不合理的,但错误信息应该更具描述性。下面有一个解决方法。
此处的问题是,我在使用application/json
时请求回复TestingViewFactory
。
让我们来看看GetModel<T>();
public static TType GetModel<TType>(this BrowserResponse response)
{
return (TType)response.Context.Items[TestingViewContextKeys.VIEWMODEL];
}
这只是从NancyContext
抓取视图模型并将其转换为您的类型。 这是引发错误的地方,因为NancyContext
中没有视图模型。这是因为视图模型以RenderView
的{{1}}方法添加到NancyContext。
TestingViewFactory
我的测试是请求json,因此不会调用RenderView。这意味着如果您使用html请求,则只能使用public Response RenderView(string viewName, dynamic model, ViewLocationContext viewLocationContext)
{
// Intercept and store interesting stuff
viewLocationContext.Context.Items[TestingViewContextKeys.VIEWMODEL] = model;
viewLocationContext.Context.Items[TestingViewContextKeys.VIEWNAME] = viewName;
viewLocationContext.Context.Items[TestingViewContextKeys.MODULENAME] = viewLocationContext.ModuleName;
viewLocationContext.Context.Items[TestingViewContextKeys.MODULEPATH] = viewLocationContext.ModulePath;
return this.decoratedViewFactory.RenderView(viewName, model, viewLocationContext);
}
。
解决方法强>
我的申请是api,所以我没有任何意见,所以改变行
GetModel<T>
到
with.Header("accept", "application/json");
将抛出with.Header("accept", "text/html");
。为避免这种情况,我需要实现自己的ViewNotFoundException
。 (这来自the.fringe.ninja)
IViewFactory
然后只是一个更新的案例
public class TestViewFactory : IViewFactory
{
#region IViewFactory Members
public Nancy.Response RenderView(string viewName, dynamic model, ViewLocationContext viewLocationContext)
{
viewLocationContext.Context.Items[Fixtures.SystemUnderTest.ViewModelKey] = model;
return new HtmlResponse();
}
#endregion
}
到
with.ViewFactory<TestingViewFactory>();
现在with.ViewFactory<TestViewFactory>();
可以在不需要视图的情况下工作。