A .Net Library for Hoverfly (http://hoverfly.io/)
Hoverfly is maintained by SpectoLabs (https://specto.io/)
Hoverfly DotNet on Nuget https://www.nuget.org/packages/Hoverfly-DotNet/
NOTE: Only work for .Net Framework Test Project, not yet for .Net Core. The Core code is a .Net Standard 2 Class Library
Hoverfly is a lightweight service virtualisation tool which allows you to stub / simulate HTTP(S) services. It is a proxy written in Go which responds to HTTP(S) requests with stored responses, pretending to be it’s real counterpart.
It enables you to get around common testing problems caused by external dependencies, such as non-deterministic data, flakiness, not yet implemented API’s, licensing fees, slow tests and more.
Hoverfly .Net is a native language binding which gives you an expressive API for managing Hoverfly in .Net. It gives you a Hoverfly class which abstracts away the binary and API calls.
NOTE: If you run the tests in parallel you can only at the moment have one Hoverfly process started. In those cases you need to start the process before all tests will be running, and stop when all tests are done. BUT you can only have one simulation loaded, or you can first use hoverfly.GetSimulation method to get the current Simulation, then modify the Simulation object and then use hoverfly.ImportSimulation to import the “new” Simulation.
Run build.ps1, it will download Hoverfly 32-bit and 64-bit version. (Default the 64-bit will be used)
Note: Hoverfly will be downloaded to the folder ".hoverfly", in the directory where you run the buid script from.
You can also download Hoverfly from:
32-bit https://github.com/SpectoLabs/hoverfly/releases/download/v1.0.1/hoverfly_bundle_windows_386.zip
64-bit https://github.com/SpectoLabs/hoverfly/releases/download/v1.0.1/hoverfly_bundle_windows_amd64.zip
By default Hoverfly DotNet will first use the HoverflyConfig.HoverflyBasePath to locate where the Hoverfly.exe is located. If it can't find it, till will try to just run "Hoverfly.exe". If that doesn't work Hoverfly DotNet will search in the subdirectoried of the specified HoverflyConfig.HoverflyBasePath (if the config is not set, default null, the Environment current directory will be used).
var hoverfly = new Hoverfly(HoverflyMode.Simulate);
hoverfly.Start();
var result = //Use HttpClient to get content, e.g. "http://time.jsontest.com";
// This call will not reach the destination URL, insted Hoverfly will return a first call that is recorded.
var result2 = //Use HttpClient to get content, e.g. "http://time.jsontest.com";
hoverfly.Stop();
using (var runner = HoverflyRunner.StartInSimulationMode())
{
}
var hoverfly = new Hoverfly(HoverflyMode.Capture);
hoverfly.Start();
// use for example HttpClient to make a call to a URL, e.g. "http://echo.jsontest.com/key/value/one/two");
hoverfly.ExportSimulation(new FileSimulationSource("simulation.json"));
hoverfly.Stop();
using (var runner = HoverflyRunner.StartInCaptureMode("simulation.json"))
{
// All HTTP calls will be captured, and then saved to "simnulation.json"
}
var hoverfly = new Hoverfly(HoverflyMode.Simulate);
hoverfly.Start();
hoverfly.ImportSimulation(new FileSimulationSource("simulation.json"));
// use for example HttpClient to make a call to a URL, e.g. "http://echo.jsontest.com/key/value/one/two");
// and it will return the result from the imported recorded simulation
hoverfly.Stop();
using (var runner = HoverflyRunner.StartInSimulationMode("simulation.json"))
{
}
using static Hoverfly.Core.Dsl.HoverflyDsl;
using static Hoverfly.Core.Dsl.ResponseCreators;
using static Hoverfly.Core.Dsl.DslSimulationSource;
...
var hoverfly = new Hoverfly(HoverflyMode.Simulate);
hoverfly.Start();
hoverfly.ImportSimulation(Dsl(
Service("http://myservice.something.com")
.Get("/key/value/three/four")
.WillReturn(Success("Hello World!", "plain/text"))));
// Every call (using for example HttpClient) to the URL http://echo.jsontest.com/key/value/three/four
// will now return the specified success response in the imported simulation. This will happen as
// long as hoverfly is running.
var result = <Http Get Content From "http://myservice.something.com/key/value/three/four">
hoverfly.Stop();
using (var runner = HoverflyRunner.StartInSimulationMode())
{
runner.Simulate(Dsl(
Service("http://mysuper.microservice.com")
.Get("/key/value/three/four")
.WillReturn(Success("Hello World!", "text/plain"))));
var result = // Get result from "http://mysuper.microservice.com/key/value/three/four"
// using for example HttpClient will return "Hello World!"
}
hoverfly.ImportSimulation(
Dsl(
Service("http://mysuper.microservice.com")
.Get("/key/value/three/four")
.WillReturn(Success("Test", "application/json").WithDelay(2000))));
hoverfly.ImportSimulation(
Dsl(
Service("http://mysuper.microservice.com")
.AndDelay(4000)
.ForMethod(HttpMethod.GET);
Hoverfly hoverfly;
void StartUp()
{
hoverfly = new Hoverfly(HoverflyMode.Simulate);
hoverfly.ImportSimulation(new FileSimulationSource("simulation.json"));
hoverfly.Start();
}
void MyTest()
{
var myController = new MyController();
var result = myController.Get("10");
Assert.Equals(result.StatusCode, 200);
}
void TearDown()
{
hoverfly.Stop();
}
MyController, using ASP.Net Core
[Route("api/[controller]")]
public class MyController : Controller
{
[HttpGet]
public IActionResult Get(string userId)
{
// Assume this code integrates with another service (maybe a Microservice :P) over HTTP with HttpClient
// httpClient.GetAsync("http://mysuper.microservice.com/foo");
...
return result;
}
}
Hoverfly will add a Proxy and all Http calls will go through that proxy. Hoverfly will in simulation mode return a recorded result for a given Http call, so no external call will be made. With the use of hoverfly in our integration/component test we don't need to create fakes to avoid external calls. With hoverfly we can also in our tests simulate delays on certain external calls etc. For example to test timeouts etc.