Asp.Net Core 2.0 Xunit测试

3

我是新手,正在使用asp.net core。我正在测试一个控制器,该控制器将视图呈现为字符串,然后利用evo pdf来渲染视图。

一切都正常工作,我也可以成功地使用postman进行测试。但是当我使用VS 2017测试资源管理器(Xunit)调试我的测试时,我的测试应用程序出错了。 在Razor引擎中搜索位置 错误发生在我的RenderViewToString方法中,因为我的razor视图引擎无法找到要呈现的视图。搜索视图的路径与预期相同。欢迎您提供任何指导。

    //Unit Test Code
    [Fact]
    public async void GetPdf()
    {
        var response = await _client.PostAsJsonAsync<Common.DTO.Invoice>("/api/values/1", GetDummyData());

        using (var file = System.IO.File.Create(@"c:\\Test" + DateTime.Now.ToString("yyyyyMMddHHmmss") + ".pdf"))
            {
            //create a new file to write to
            await response.Content.CopyToAsync(file);
            await file.FlushAsync(); // flush back to disk before disposing
            }


    }

    //Render view to string service
    public interface IViewRenderService
    {
    Task<string> RenderToStringAsync(string viewName, ViewDataDictionary viewData);
    }
    public class ViewRenderService : IViewRenderService
    {
    private readonly IRazorViewEngine _razorViewEngine;
    private readonly ITempDataProvider _tempDataProvider;
    private readonly IServiceProvider _serviceProvider;

    public ViewRenderService(IRazorViewEngine razorViewEngine,ITempDataProvider tempDataProvider,IServiceProvider serviceProvider)
    {
        _razorViewEngine = razorViewEngine;
        _tempDataProvider = tempDataProvider;
        _serviceProvider = serviceProvider;
    }

    public async Task<string> RenderToStringAsync(string viewName, ViewDataDictionary viewData)
    {
        var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };
        var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

        using (var sw = new StringWriter())
        {
            var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);

            if (viewResult.View == null)
            {
                throw new ArgumentNullException($"{viewName} does not match any available view");
            }


            var viewContext = new ViewContext(
                actionContext,
                viewResult.View,
                viewData,
                new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
                sw,
                new HtmlHelperOptions()
            );

            await viewResult.View.RenderAsync(viewContext);
            return sw.ToString();
        }
    }

    }
2个回答

1
我之前在使用核心2.0时也遇到了同样的错误。问题出在RazorViewEngine与空的RouteData对象不兼容;因此,我注入了IHttpContextAccessor并从中获取了HttpContextRouteData

Startup.cs:

  public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IViewRenderService, ViewRenderService>();
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddMvc();
    }

RazorToStringHelper.cs:

  public interface IViewRenderService
{
    Task<string> RenderToStringAsync(string viewName, object model);
}

public class ViewRenderService : IViewRenderService
{
    private readonly IRazorViewEngine _razorViewEngine;
    private readonly ITempDataProvider _tempDataProvider;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public ViewRenderService(
        IRazorViewEngine razorViewEngine,
        IHttpContextAccessor httpContextAccessor,
        ITempDataProvider tempDataProvider)
    {
        _razorViewEngine = razorViewEngine;
        _tempDataProvider = tempDataProvider;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task<string> RenderToStringAsync(string viewName, object model)
    {
        var httpContext = _httpContextAccessor.HttpContext;

        var actionContext = new ActionContext(httpContext, httpContext.GetRouteData(), new ActionDescriptor());

        var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);

        if (viewResult.View == null)
        {
            throw new ArgumentNullException($"{viewName} does not match any available view");
        }

        using (var sw = new StringWriter())
        {
            var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
            {
                Model = model
            };

            var viewContext = new ViewContext(
                actionContext,
                viewResult.View,
                viewDictionary,
                new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
                sw,
                new HtmlHelperOptions()
            );

            await viewResult.View.RenderAsync(viewContext);
            return sw.ToString();
        }
    }

}

@BarryS 这个对你有用吗?我遇到了 _httpContextAccessor.HttpContext 返回 null 的问题。 - Jetpack

0
由于时间限制,我放弃了XUnit方法,编写了一个测试应用程序,并且还使用了Postman,因为这是从Razor视图呈现PDF的API要求。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接