Burla 🎭¶

Mocking without the nonsense¶
Burla ("prank" in Italian) is a lightweight, LLM-friendly mocking library for .NET.
It is built for explicit tests, strict defaults, and migrations that do not turn into archaeology.
Start with one awkward test, use the migration guides when the shape feels right, and keep the library surface focused for humans and AI tools alike.
-
Clean API
Blends the best of Moq's discoverability with NSubstitute's concise matchers.
Mock.Of<T>()+Arg.Any<T>()+Setup(...)— straightforward. Works across interfaces, abstract classes, and concrete classes with virtual members. -
Async-first
First-class
IAsyncEnumerable,Task, andValueTasksupport.
No helper methods needed. -
Strict by default
Unconfigured calls throw immediately — no silent bugs.
Opt in to loose mode when you need it. -
LLM-friendly
Setup, argument matching, and verification follow consistent patterns that AI assistants can generate reliably. More of the prompt stays available for the test and production code instead of mock-library quirks.
Includes a migration prompt for automated conversion.
Quick comparison¶
| Feature | Moq | NSubstitute | Burla |
|---|---|---|---|
IAsyncEnumerable |
Helper methods needed | Helper methods needed | First-class |
| Ref/Out parameters | Verbose delegates | Limited support | Clean syntax |
| Strict mode | Opt-in | ❌ Not available | Default ✅ |
| Verification | Library-specific API | Library-specific API | Standard assertions |
| Arg matchers | It.IsAny<T>() |
Arg.Any<T>() |
Arg.Any<T>() |
Quick start¶
using Burla;
// Create a strict mock (default)
var mock = Mock.Of<ICalculator>();
// Setup behavior
mock.Setup(x => x.Add(Arg.Any<int>(), Arg.Any<int>())).Returns(42);
// Use it
var result = mock.Instance.Add(1, 2); // returns 42
// Verify using standard xUnit assertions
var calls = mock.CallsTo(x => x.Add(1, 2));
Assert.Single(calls);
Burla-native docs teach verification through CallsTo(...) + standard assertions. Verify(..., Times...) is still available, mainly for low-diff Moq migrations and for VerifyNoOtherCalls().
Burla-native docs use .Instance as the default spelling for the runtime double. If you only need the runtime value, Mock.Create<T>() and Mock.CreateLoose<T>() return it directly; .Object remains available as a Moq compatibility alias.
Install¶
Use Burla.Core instead if you want the runtime package without IDE analyzers and code fixes.
Burla is the meta-package (Burla.Core + Burla.Analyzers), while Burla.Analyzers is also available directly if you only want the IDE suggestions/code fixes package.
The BURLA01x compatibility analyzer rules default to info. If you want a quieter Moq migration, lower BURLA010, BURLA011, and BURLA012 to silent or none in .editorconfig.
Native API at a glance¶
Mock.Of<T>()/Mock.OfLoose<T>()create mock wrappers;Mock.Create<T>()/Mock.CreateLoose<T>()return the runtime value directlymock.Instanceis the native runtime propertySetup(...)/SetupSet(...)configure behavior;Arg.*supplies matchersCallsTo(...)+ standard assertions is the default verification style, withVerify(..., Times...)andVerifyNoOtherCalls()available when they helpMock.Sequence()/.InSequence(...)handle ordered verificationSetsByRefParameter(...)configuresref/outwritebackmock.Event(name).Emit(...)emits eventsmock.Reset()clears mutable state without recreating the runtime instance.Object,It.*, andSetupGet(...)remain available as thin migration aliases, with analyzersBURLA010,BURLA011,BURLA012, andBURLA020
Next steps¶
- Getting Started — full walkthrough with examples
- API Guide — complete reference, including class mocking,
CallsTo(...), and optional verification helpers - Migrate from Moq
- Migrate from NSubstitute
- LLM Migration Reference
What Burla 1.0 covers¶
Burla 1.0 covers the mocking workflows most teams need in day-to-day test suites, with a focused API that stays easy to learn, easy to read in reviews, and practical to adopt in existing codebases.
It focuses on the patterns most teams hit every day. One notable advanced case still out of scope for 1.0 is protected-member setup.
License¶
MIT — free forever. No pranks here. 🤝