如何测试asp.net核心1.1 mvc动作使用microsoft.aspnetcore.testhost

时间:2017-03-11 16:03:19

标签: unit-testing razor asp.net-core

使用Microsoft.aspnetcore.testhost我无法让http到控制器操作返回razor视图。我需要测试响应是否有特定的安全标头,并且我想对动作响应执行其他测试。 Razor会为它命中的每个命名空间抛出编译异常,而不仅仅是下面的系统示例:

oclq12bb.ugz(5,11): error CS0246: The type or namespace name 'System' could
not be found (are you missing a using directive or an assembly reference?)
oclq12bb.ugz(6,11): error CS0246: The type or namespace name 'System' could
not be found (are you missing a using directive or an assembly reference?)

摄制:

  • 使用visual studio 2017创建一个新的asp.net核心1.1 Web项目 并添加一个.net核心单元测试项目。
  • 从启动中删除appsettings。
  • 将视图/home/index.cshtml设置为复制到输出目录为“始终复制”。
  • 创建并运行单元测试。引发异常。

代码:

[TestClass]
public class UnitTest1
{
    private readonly HttpClient _client;

    public UnitTest1()
    {
        var server = new TestServer(
            new WebHostBuilder().UseStartup<Startup>());
        _client = server.CreateClient();
    }

    [TestMethod]
    public async Task Test1()
    {
        var response = await _client.GetAsync("/");
    }
}

我尝试将Web项目发布到文件夹,并始终使用.UseContentRoot()代替复制。结果相同。

1 个答案:

答案 0 :(得分:4)

longday的评论实际上对我有用。为了使这个问题得到解答并对其他人更有用,让我把实际的代码放在有效的位置。这是我项目中的代码,但它非常通用。

using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.TestHost;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.PlatformAbstractions;
using Shevastream.Models;
using Shevastream.Services.Factories;
using Xunit;

namespace Shevastream.Tests.IntegrationTests
{
    public class PagesTests
    {
        /// <summary>
        /// Server object which mimics a real running server
        /// </summary>
        private readonly TestServer _server;
        /// <summary>
        /// Client object which mimics a real client
        /// </summary>
        private readonly HttpClient _client;

        private readonly IDataContext _dataContext;

        /// <summary>
        /// Setup mock server and client
        /// </summary>
        public PagesTests()
        {
            var path = PlatformServices.Default.Application.ApplicationBasePath;
            var contentPath = Path.GetFullPath(Path.Combine(path, $@"../../../../src"));

            _server = new TestServer(
                new WebHostBuilder()
                    .UseContentRoot(contentPath)
                    .UseStartup<Startup>()
                    .ConfigureServices(services =>
                    {
                        services.AddSingleton<IHttpClientFactory, HttpClientFactory>();
                        services.Configure((RazorViewEngineOptions options) =>
                        {
                            var previous = options.CompilationCallback;
                            options.CompilationCallback = (context) =>
                            {
                                previous?.Invoke(context);

                                var assembly = typeof(Startup).GetTypeInfo().Assembly;
                                var assemblies = assembly.GetReferencedAssemblies().Select(x => MetadataReference.CreateFromFile(Assembly.Load(x).Location))
                                .ToList();
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("mscorlib")).Location));
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Private.Corelib")).Location));
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("Microsoft.AspNetCore.Razor")).Location));
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("mscorlib")).Location)); 
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Private.Corelib")).Location)); 
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Linq")).Location)); 
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Threading.Tasks")).Location)); 
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Runtime")).Location)); assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Dynamic.Runtime")).Location)); 
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("Microsoft.AspNetCore.Razor.Runtime")).Location)); 
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("Microsoft.AspNetCore.Mvc")).Location)); 
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("Microsoft.AspNetCore.Razor")).Location)); 
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("Microsoft.AspNetCore.Mvc.Razor")).Location));
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("Microsoft.AspNetCore.Html.Abstractions")).Location)); 
                                assemblies.Add(MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Text.Encodings.Web")).Location));

                                context.Compilation = context.Compilation.AddReferences(assemblies);
                            };
                        });
                    })
            );

            _client = _server.CreateClient();

            var serviceProvider = Extensions.RegisterServices().BuildServiceProvider();
            _dataContext = serviceProvider.GetRequiredService<IDataContext>();
        }

        [Theory]
        [InlineData("/home")]
        [InlineData("/home/profile")]
        [InlineData("/store/product")]
        [InlineData("/home/contact")]
        [InlineData("/store/cart")]
        [InlineData("/home/faq")]
        [InlineData("/account/login")]
        public async Task TestSimplePages(string url)
        {
            // Act
            var ok = await _client.GetAsync(url);

            // Assert
            Assert.Equal(HttpStatusCode.OK, ok.StatusCode);
        }
    }
}