I have a .NET project which depends on a database that I am writing integration tests for. When I run the tests I need a local docker container to be running. It can be started using the following command (from the solution root):
docker compose up -d db
For now, this is simple enough to do manually but, ideally, standing up the container would be automated whenever the tests are run. To this end I tried the adding following:
(solution root)/Directory.Build.props:
<SolutionRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)'))</SolutionRoot>
(solution root)/tests/IntegrationTests/IntegrationTests.csproj:
<Target Name="DbContainerUp" BeforeTargets="VSTest">
<Exec Command="cd $(SolutionRoot)" />
<Exec Command="docker compose up -d db" />
</Target>
This works but only when executed via dotnet test. If I execute the tests using either Visual Studio Test Explorer or VSCode Test Runner then the DbContainerUp target is not invoked. I assume this is because the Test Explorer/Runner does not invoke dotnet msbuild /t:VSTest (which is what dotnet test is translated to) but I am unable to find any documentation of what targets (if any) VS and VSCode use.
I have looked into the following and not found a viable path forward yet:
.runsettings does not provide an extensibility point for executing commands.For now I have solved this by adding an AfterTargets="AfterBuild" attribute to the DbContainerUp target like so:
<Target Name="DbContainerUp" BeforeTargets="VSTest" AfterTargets="AfterBuild">
<Exec Command="cd $(SolutionRoot)" />
<Exec Command="docker compose up -d db" />
</Target>
This works because VS (and VS Code) must build the IntegrationTests project as part of either test discovery or prior to test execution (depending on implementation). Additionally, because BeforeTargets and AfterTargets are cooperative (either will trigger the custom target), this means that dotnet test continues to behave as expected.
While this isn't a perfect solution--any generic dotnet build will also start the container--it is acceptable for our needs to ensure the container is started.