我有一个启动CS,我在其中注册AuthenticationMiddleware是这样的:
public class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
AddAuthentication(app);
app.UseMvcWithDefaultRoute();
app.UseStaticFiles();
}
protected virtual void AddAuthentication(IApplicationBuilder app)
{
app.UseAuthentication();
}
}
我用以下方法进行测试:
WebApplicationFactory<Startup>().CreateClient();
我想用app.UseAuthentication();
代替app.UseMiddleware<TestingAuthenticationMiddleware>()
,
我在我的测试项目中考虑过从Startup继承:
public class TestStartup : Startup
{
protected override void AddAuthentication(IApplicationBuilder app)
{
app.UseMiddleware<AuthenticatedTestRequestMiddleware>();
}
}
class TestWebApplicationFactory : WebApplicationFactory<Web.Startup>
{
protected override IWebHostBuilder CreateWebHostBuilder()
{
return WebHost.CreateDefaultBuilder()
.UseStartup<IntegrationTestProject.TestStartup>();
}
}
但是这不起作用,因为TestStartup在另一个程序集中,这对WebHost.CreateDefaultBuilder()
有很多副作用
我得到:
System.ArgumentException:内容根 'C:\ Projects \ Liero \ myproject \ tests \ IntegrationTests'不存在。 参数名称:contentRootPath
答案 0 :(得分:2)
我遇到了同样的问题,并像这样解决了;
/// <summary>
/// A test fixture which hosts the target project (project we wish to test) in an in-memory server.
/// </summary>
/// <typeparam name="TStartup">Target project's startup type</typeparam>
/// <typeparam name="DStartup">Decorated startup type</typeparam>
public class TestFixture<DStartup, TStartup> : IDisposable
{
private readonly TestServer _server;
public TestFixture()
: this(Path.Combine("YourRelativeTargetProjectParentDir"))
{
}
protected TestFixture(string relativeTargetProjectParentDir)
{
var startupAssembly = typeof(TStartup).GetTypeInfo().Assembly;
var contentRoot = GetProjectPath(relativeTargetProjectParentDir, startupAssembly);
//var integrationTestsPath = PlatformServices.Default.Application.ApplicationBasePath;
//var contentRoot = Path.GetFullPath(Path.Combine(integrationTestsPath, "../../../../MinasTirith"));
var builder = new WebHostBuilder()
.UseContentRoot(contentRoot)
.ConfigureServices(InitializeServices)
.UseEnvironment("Development")
.UseStartup(typeof(DStartup));
_server = new TestServer(builder);
Client = _server.CreateClient();
Client.BaseAddress = new Uri("http://localhost:5000");
}
public HttpClient Client { get; }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
Client.Dispose();
_server.Dispose();
}
protected virtual void InitializeServices(IServiceCollection services)
{
var startupAssembly = typeof(TStartup).GetTypeInfo().Assembly;
// Inject a custom application part manager.
// Overrides AddMvcCore() because it uses TryAdd().
var manager = new ApplicationPartManager();
manager.ApplicationParts.Add(new AssemblyPart(startupAssembly));
manager.FeatureProviders.Add(new ControllerFeatureProvider());
manager.FeatureProviders.Add(new ViewComponentFeatureProvider());
services.AddSingleton(manager);
}
/// <summary>
/// Gets the full path to the target project that we wish to test
/// </summary>
/// <param name="projectRelativePath">
/// The parent directory of the target project.
/// e.g. src, samples, test, or test/Websites
/// </param>
/// <param name="startupAssembly">The target project's assembly.</param>
/// <returns>The full path to the target project.</returns>
private static string GetProjectPath(string projectRelativePath, Assembly startupAssembly)
{
// Get name of the target project which we want to test
var projectName = startupAssembly.GetName().Name;
// Get currently executing test project path
var applicationBasePath = System.AppContext.BaseDirectory;
// Find the path to the target project
var directoryInfo = new DirectoryInfo(applicationBasePath);
do
{
directoryInfo = directoryInfo.Parent;
var projectDirectoryInfo = new DirectoryInfo(Path.Combine(directoryInfo.FullName, projectRelativePath));
if (projectDirectoryInfo.Exists)
{
var projectFileInfo = new FileInfo(Path.Combine(projectDirectoryInfo.FullName, projectName, $"{projectName}.csproj"));
if (projectFileInfo.Exists)
{
return Path.Combine(projectDirectoryInfo.FullName, projectName);
}
}
}
while (directoryInfo.Parent != null);
throw new Exception($"Project root could not be located using the application root {applicationBasePath}.");
}
}
我在这样的单元测试方法中使用它;
[TestInitialize]
public void BeforeEachTest()
{
testFixture = new TestFixture<TestStartup, Startup>();
//this is my HttpClient variable
client = testFixture.Client;
}
P.S。这是我用于项目的确切代码段。
答案 1 :(得分:2)
似乎WebApplicationFactory应该使用实际的Startup类作为类型参数:
class TestWebApplicationFactory : WebApplicationFactory<Startup>
{
protected override IWebHostBuilder CreateWebHostBuilder()
{
return WebHost.CreateDefaultBuilder<TestableStartup>(new string[0]);
}
}