Write API tests using Visual Studio’s .http file format with variables, environments, and request chaining.
The .http file format lets you define HTTP requests in a readable text format. Breakdance’s DotHttp library
provides a runtime and source generator to execute these files as unit tests, with full support for variables,
environments, and request chaining.
Create a test class that inherits from DotHttpTestBase:
ApiTests.cs
using CloudNimble.Breakdance.DotHttp;using CloudNimble.Breakdance.DotHttp.Models;using Microsoft.VisualStudio.TestTools.UnitTesting;using System.Net.Http;using System.Threading.Tasks;[TestClass]public class ApiTests : DotHttpTestBase{ [TestMethod] public async Task GetUsers_ReturnsSuccess() { SetVariable("baseUrl", "https://jsonplaceholder.typicode.com"); var request = new DotHttpRequest { Method = "GET", Url = "{{baseUrl}}/users", Name = "getUsers" }; var response = await SendRequestAsync(request); Assert.IsTrue(response.IsSuccessStatusCode); }}
While you can manually construct DotHttpRequest objects, the real power comes from parsing .http files
or using the source generator to create tests automatically.
A .http file contains one or more HTTP requests separated by ###:
api.http
### Get all usersGET https://api.example.com/usersAccept: application/json### Create a userPOST https://api.example.com/usersContent-Type: application/json{ "name": "John Doe", "email": "john@example.com"}### Get a specific userGET https://api.example.com/users/1
Use # @name to give a request a name for later reference:
### Login to get a token# @name loginPOST {{baseUrl}}/auth/loginContent-Type: application/json{"username": "test", "password": "secret"}### Use the token from loginGET {{baseUrl}}/users/meAuthorization: Bearer {{login.response.body.$.token}}
Combine DotHttp testing with cached responses for deterministic tests:
public class CachedApiTests : DotHttpTestBase{ protected override HttpMessageHandler CreateHttpMessageHandler() { // Serve responses from cached files instead of real API return new TestCacheReadDelegatingHandler("ResponseFiles"); } [TestMethod] public async Task GetUsers_UseCachedResponse() { SetVariable("baseUrl", "https://api.example.com"); var response = await SendRequestAsync(new DotHttpRequest { Method = "GET", Url = "{{baseUrl}}/users" }); // Response comes from ResponseFiles/api.example.com/users.json Assert.IsTrue(response.IsSuccessStatusCode); }}