diff --git a/HistoryContest.Test/WebAPITest/TestFixture.cs b/HistoryContest.Test/WebAPITest/TestFixture.cs
new file mode 100644
index 0000000..687d32a
--- /dev/null
+++ b/HistoryContest.Test/WebAPITest/TestFixture.cs
@@ -0,0 +1,103 @@
+using System;
+using System.IO;
+using System.Net.Http;
+using System.Reflection;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc.ApplicationParts;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.ViewComponents;
+using Microsoft.AspNetCore.TestHost;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.PlatformAbstractions;
+
+namespace XUnitTest.WebAPItest.IntegrationTest
+{
+ ///
+ /// A test fixture which hosts the target project (project we wish to test) in an in-memory server.
+ ///
+ /// Target project's startup type
+ public class TestFixture : IDisposable
+ {
+ private const string SolutionName = "HistoryContest.sln";
+ private readonly TestServer _server;
+
+ public TestFixture()
+ : this(Path.Combine("src"))
+ {
+ }
+
+ protected TestFixture(string solutionRelativeTargetProjectParentDir)
+ {
+ var startupAssembly = typeof(TStartup).GetTypeInfo().Assembly;
+ var contentRoot = GetProjectPath(solutionRelativeTargetProjectParentDir, startupAssembly);
+
+ var builder = new WebHostBuilder()
+ .UseContentRoot(contentRoot)
+ .ConfigureServices(InitializeServices)
+ .UseEnvironment("Development")
+ .UseStartup(typeof(TStartup));
+
+ _server = new TestServer(builder);
+
+ Client = _server.CreateClient();
+ Client.BaseAddress = new Uri("http://localhost");
+ }
+
+ public HttpClient Client { get; }
+
+ public void Dispose()
+ {
+ 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 that 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);
+ }
+
+ ///
+ /// Gets the full path to the target project path that we wish to test
+ ///
+ ///
+ /// The parent directory of the target project.
+ /// e.g. src, samples, test, or test/Websites
+ ///
+ /// The target project's assembly.
+ /// The full path to the target project.
+ private static string GetProjectPath(string solutionRelativePath, 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 = PlatformServices.Default.Application.ApplicationBasePath;
+
+ // Find the folder which contains the solution file. We then use this information to find the target
+ // project which we want to test.
+ var directoryInfo = new DirectoryInfo(applicationBasePath);
+ do
+ {
+ var solutionFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, SolutionName));
+ if (solutionFileInfo.Exists)
+ {
+ return Path.GetFullPath(Path.Combine(directoryInfo.FullName, solutionRelativePath, projectName));
+ }
+
+ directoryInfo = directoryInfo.Parent;
+ }
+ while (directoryInfo.Parent != null);
+
+ throw new Exception($"Solution root could not be located using application root {applicationBasePath}.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/HistoryContest.Test/WebAPITest/WebAPITest.cs b/HistoryContest.Test/WebAPITest/WebAPITest.cs
index 8f28206..95132f6 100644
--- a/HistoryContest.Test/WebAPITest/WebAPITest.cs
+++ b/HistoryContest.Test/WebAPITest/WebAPITest.cs
@@ -9,7 +9,7 @@
using HistoryContest.Server.Controllers.APIs;
using Xunit;
-namespace XUnitTest.IntegrationTest.WebAPItest
+namespace XUnitTest.WebAPItest.IntegrationTest
{
public class ApiIdeasControllerTests : IClassFixture>
{