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> {