testwire 0.1.0
See the version list below for details.
dotnet tool install --global testwire --version 0.1.0
dotnet new tool-manifest
dotnet tool install --local testwire --version 0.1.0
#tool dotnet:?package=testwire&version=0.1.0
nuke :add-package testwire --version 0.1.0
<div align="center">
🔌 TestWire
Automatically generate xUnit/NUnit test stubs for your ASP.NET Web APIs.
Stop writing boilerplate. Just run and ship.
</div>
Why TestWire?
You've written the controller. You've wired up the endpoints. Now you have to write 20 nearly identical test stubs before you can even start testing real logic.
TestWire reads your .csproj, finds every controller and endpoint via Roslyn, and writes those stubs for you — with mocked dependencies, real DTO shapes, and happy/bad path coverage out of the box.
dotnet tool install -g testwire
testwire generate --project ./MyApi/MyApi.csproj --output ./tests
Analyzing /path/to/MyApi.csproj...
✅ Written → ./tests/ProductsControllerTests.cs
[GET] GetById → api/products/{id}
[POST] Create → api/products
✅ Written → ./tests/OrdersControllerTests.cs
[DELETE] Delete → api/orders/{id}
What Gets Generated
For every controller TestWire finds, it produces a test file with:
- Happy path — a
200 OK/201 Createdtest with a valid request - Bad path — a
400 BadRequesttest with invalid inputs - Auth test — a
401 Unauthorizedtest when[Authorize]is present - Mocked constructor dependencies — every injected interface becomes a
Mock<T>via Moq - DTO stubs with real property values — generated from your model shapes, not placeholders
// Input — your controller
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _service;
public ProductsController(IProductService service) { _service = service; }
[HttpPost]
public async Task<IActionResult> Create([FromBody] CreateProductDto dto) { ... }
}
// Output — generated by TestWire
public class ProductsControllerTests
{
private readonly Mock<IProductService> _mockService = new();
private readonly ProductsController _sut;
public ProductsControllerTests()
{
_sut = new ProductsController(_mockService.Object);
}
[Fact]
public async Task Create_ReturnsCreated_WhenRequestIsValid()
{
// Arrange
var dto = new CreateProductDto { Name = "TestName", Price = 1 };
// Act
var result = await _sut.Create(dto);
// Assert
result.Should().BeOfType<CreatedAtActionResult>();
}
[Fact]
public async Task Create_ReturnsBadRequest_WhenRequestIsInvalid()
{
// Arrange
var dto = new CreateProductDto { Name = "", Price = -1 };
// Act
var result = await _sut.Create(dto);
// Assert
result.Should().BeOfType<BadRequestObjectResult>();
}
}
Installation
Requires .NET 8+
dotnet tool install -g testwire
Usage
Basic
testwire generate --project ./MyApi/MyApi.csproj
Scans your project and writes test files to ./TestWire.Generated/ by default.
Custom output directory
testwire generate --project ./MyApi/MyApi.csproj --output ./tests
Preview without writing files
testwire generate --project ./MyApi/MyApi.csproj --dry-run
Use NUnit instead of xUnit
testwire generate --project ./MyApi/MyApi.csproj --framework nunit
All Options
| Flag | Description | Default |
|---|---|---|
--project |
Path to the .csproj file (required) |
— |
--output |
Directory to write generated test files | ./TestWire.Generated |
--framework |
Test framework: xunit or nunit |
xunit |
--dry-run |
Print output to console, don't write files | false |
Current Limitations (v0.1)
This is an early release. Here's what's not supported yet:
[FromQuery]and[FromHeader]parameters are not yet analyzed- Mock setup (
.Setup(...)) is not generated — stubs use default mock behavior - No
--controllerflag to target a single controller - No
.csprojfile is created for the output test folder
If any of these block you, please open an issue.
Contributing
PRs and issues are welcome. Open an issue to discuss what you'd like to change before submitting a PR.
License
MIT © Mazen Hassan
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.