<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Diego Teles</title>
    <description>The latest articles on DEV Community by Diego Teles (@guinhx).</description>
    <link>https://dev.to/guinhx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3660621%2F422d32a8-feae-40fd-b1e9-29c743f71119.jpeg</url>
      <title>DEV Community: Diego Teles</title>
      <link>https://dev.to/guinhx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/guinhx"/>
    <language>en</language>
    <item>
      <title>Porting Zod to C#: ZodSharp – A Zero-Allocation, High-Performance Schema Validation Library for .NET</title>
      <dc:creator>Diego Teles</dc:creator>
      <pubDate>Sun, 14 Dec 2025 00:05:05 +0000</pubDate>
      <link>https://dev.to/guinhx/porting-zod-to-c-zodsharp-a-zero-allocation-high-performance-schema-validation-library-for-net-1i4</link>
      <guid>https://dev.to/guinhx/porting-zod-to-c-zodsharp-a-zero-allocation-high-performance-schema-validation-library-for-net-1i4</guid>
      <description>&lt;h1&gt;
  
  
  Porting Zod to C#: ZodSharp – A Zero-Allocation, High-Performance Schema Validation Library for .NET
&lt;/h1&gt;

&lt;p&gt;As a .NET developer, I’ve long been frustrated by one persistent pain point: most validation libraries rely heavily on reflection, leading to slow performance and constant allocations. Whether it’s validating API inputs, forms, or data pipelines, that overhead adds up — especially in high-throughput scenarios.&lt;/p&gt;

&lt;p&gt;Then I discovered &lt;strong&gt;Zod&lt;/strong&gt; — the gold standard for schema validation in the TypeScript world, created by &lt;em&gt;colinhacks&lt;/em&gt;. Its fluent API, full type inference, excellent error messages, and zero-dependency design made it feel like magic. But there was nothing quite like it in C#.&lt;/p&gt;

&lt;p&gt;So I decided to change that. I built &lt;strong&gt;ZodSharp&lt;/strong&gt; — a complete, from-scratch rewrite of Zod tailored for modern .NET, with a relentless focus on &lt;strong&gt;performance, zero-allocation, and developer experience&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This post is the story of that journey and why ZodSharp might just become your new go-to validation library.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why Zod Became the Standard in TypeScript
&lt;/h3&gt;

&lt;p&gt;Zod dominates the JS/TS ecosystem for good reason:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fluent, chainable API&lt;/strong&gt; that's a joy to write&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full type safety&lt;/strong&gt; with automatic inference&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Powerful composition&lt;/strong&gt; for complex schemas&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rich transforms and refinements&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clear, structured error reporting&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero runtime dependencies&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In .NET, we have solid options like FluentValidation, but they lean on reflection and expressions — great for flexibility, but costly in performance-critical paths.&lt;/p&gt;

&lt;p&gt;ZodSharp brings that same elegant developer experience to C# — &lt;strong&gt;without the allocation tax&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Not a Simple Port — A Performance-First Rewrite
&lt;/h3&gt;

&lt;p&gt;While staying faithful to Zod’s public API and semantics, nearly every internal detail was re-engineered for .NET’s strengths.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zero-Allocation: The Core Design Goal
&lt;/h3&gt;

&lt;p&gt;The #1 priority: validation should produce &lt;strong&gt;zero garbage&lt;/strong&gt; in hot paths.&lt;/p&gt;

&lt;p&gt;Reflection-based validation creates objects, closures, and temporary collections on every call. ZodSharp eliminates that entirely.&lt;/p&gt;

&lt;p&gt;Key techniques:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Validation rules as structs&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;MinLengthRule&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IValidationRule&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;_min&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MinLengthRule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_min&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

       &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;_min&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Immutable collections with minimal overhead&lt;/strong&gt; (&lt;code&gt;ImmutableArray&lt;/code&gt;, &lt;code&gt;ImmutableDictionary&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ValidationResult as a struct&lt;/strong&gt; — no heap allocation on success or failure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ArrayPool for any temporary buffers&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manual loops instead of LINQ&lt;/strong&gt; in performance-critical sections&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Span and ReadOnlySpan&lt;/strong&gt; for string operations with zero copies&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Fluent API — As Close to Zod as Possible
&lt;/h3&gt;

&lt;p&gt;The API feels instantly familiar to Zod users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Almost identical to Zod TS&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Object schemas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;userSchema&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;120&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Transforms, refinements, unions, optionals, literals — all supported.&lt;/p&gt;




&lt;h3&gt;
  
  
  Source Generators &amp;amp; DataAnnotations Integration
&lt;/h3&gt;

&lt;p&gt;One of the biggest .NET-specific wins: &lt;strong&gt;compile-time schema generation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Decorate a class with &lt;code&gt;[ZodSchema]&lt;/code&gt; and use standard &lt;code&gt;DataAnnotations&lt;/code&gt; — ZodSharp generates a static schema at build time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ZodSchema&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Required&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;StringLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MinimumLength&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;120&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;EmailAddress&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No runtime reflection needed.&lt;/p&gt;




&lt;h3&gt;
  
  
  Project Architecture Overview
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ZodSharp/
├── src/ZodSharp/
│   ├── Core/                → Interfaces, base classes, results, errors
│   ├── Schemas/             → String, Number, Object, Array, Union, etc.
│   ├── Rules/               → Struct-based validation rules
│   ├── Expressions/         → Compiled validators via Expression Trees
│   ├── Json/                → Newtonsoft.Json integration
│   ├── Optimizations/       → Zero-allocation helpers
│   └── Z.cs                 → Static factory (Z.String(), Z.Object(), etc.)
├── src/ZodSharp.SourceGenerators/
│   └── ZodSchemaGenerator.cs → [ZodSchema] source generator
├── example/                 → Full usage samples
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Rough Performance Wins
&lt;/h3&gt;

&lt;p&gt;Early benchmarks show dramatic improvements over typical reflection-based validation:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Reflection-Based&lt;/th&gt;
&lt;th&gt;ZodSharp&lt;/th&gt;
&lt;th&gt;Gain&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simple string validation&lt;/td&gt;
&lt;td&gt;~0.15 ms&lt;/td&gt;
&lt;td&gt;~0.01 ms&lt;/td&gt;
&lt;td&gt;~15× faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complex object validation&lt;/td&gt;
&lt;td&gt;~0.8 ms&lt;/td&gt;
&lt;td&gt;~0.05 ms&lt;/td&gt;
&lt;td&gt;~16× faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Allocations per validation&lt;/td&gt;
&lt;td&gt;Multiple&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Zero&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Eliminated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The gap widens under load.&lt;/p&gt;




&lt;h3&gt;
  
  
  Practical Use Cases
&lt;/h3&gt;

&lt;p&gt;ZodSharp shines anywhere validation performance matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-throughput APIs (REST, gRPC, GraphQL)&lt;/li&gt;
&lt;li&gt;Microservices with frequent input validation&lt;/li&gt;
&lt;li&gt;Real-time systems&lt;/li&gt;
&lt;li&gt;Data ingestion pipelines&lt;/li&gt;
&lt;li&gt;Desktop/mobile apps with complex forms&lt;/li&gt;
&lt;li&gt;Anywhere you want Zod-like DX without the runtime cost&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  What’s Already Implemented
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fluent schema building&lt;/li&gt;
&lt;li&gt;Full primitive support (string, number, boolean, array, object, union, literal)&lt;/li&gt;
&lt;li&gt;Transforms (&lt;code&gt;.Trim()&lt;/code&gt;, &lt;code&gt;.ToLower()&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Refinements (custom validation)&lt;/li&gt;
&lt;li&gt;Optional / nullable wrappers&lt;/li&gt;
&lt;li&gt;Discriminated unions&lt;/li&gt;
&lt;li&gt;Lazy/recursive schemas&lt;/li&gt;
&lt;li&gt;Source generator with DataAnnotations&lt;/li&gt;
&lt;li&gt;Newtonsoft.Json integration&lt;/li&gt;
&lt;li&gt;Advanced string rules (&lt;code&gt;.Url()&lt;/code&gt;, &lt;code&gt;.Uuid()&lt;/code&gt;, &lt;code&gt;.Email()&lt;/code&gt;, &lt;code&gt;.StartsWith()&lt;/code&gt;...)&lt;/li&gt;
&lt;li&gt;Advanced number rules (&lt;code&gt;.Positive()&lt;/code&gt;, &lt;code&gt;.MultipleOf()&lt;/code&gt;, &lt;code&gt;.Finite()&lt;/code&gt;...)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  What’s Next?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Public benchmark suite&lt;/li&gt;
&lt;li&gt;ASP.NET Core model binding integration&lt;/li&gt;
&lt;li&gt;Entity Framework validation hooks&lt;/li&gt;
&lt;li&gt;More JSON serializer support (System.Text.Json)&lt;/li&gt;
&lt;li&gt;Enhanced error formatting&lt;/li&gt;
&lt;li&gt;Community contributions!&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Building ZodSharp was incredibly rewarding. It wasn’t just about bringing Zod to C# — it was about solving a real, widespread pain in the .NET ecosystem: &lt;strong&gt;fast, type-safe, zero-overhead validation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you’ve ever groaned at reflection slowdowns or wished for a more modern validation experience in C#, I hope you’ll give ZodSharp a try.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/guinhx/ZodSharp" rel="noopener noreferrer"&gt;https://github.com/guinhx/ZodSharp&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;NuGet:&lt;/strong&gt; &lt;a href="https://www.nuget.org/packages/ZodSharp" rel="noopener noreferrer"&gt;https://www.nuget.org/packages/ZodSharp&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Original Zod:&lt;/strong&gt; &lt;a href="https://github.com/colinhacks/zod" rel="noopener noreferrer"&gt;https://github.com/colinhacks/zod&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback, stars, issues, and PRs are very welcome! Let me know — have you felt the reflection validation pain? What would make you switch?&lt;/p&gt;

&lt;p&gt;Thanks for reading! 🚀&lt;/p&gt;

&lt;p&gt;Tags: #dotnet #csharp #validation #zod #performance #opensource #typesafety&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>validation</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Porting Mistreevous to C#: A High-Performance Behavior Tree Library for Modern .NET</title>
      <dc:creator>Diego Teles</dc:creator>
      <pubDate>Sun, 14 Dec 2025 00:02:40 +0000</pubDate>
      <link>https://dev.to/guinhx/porting-mistreevous-to-c-a-high-performance-behavior-tree-library-for-modern-net-l4p</link>
      <guid>https://dev.to/guinhx/porting-mistreevous-to-c-a-high-performance-behavior-tree-library-for-modern-net-l4p</guid>
      <description>&lt;h1&gt;
  
  
  Porting Mistreevous to C#: A High-Performance Behavior Tree Library for Modern .NET
&lt;/h1&gt;

&lt;p&gt;When I started building dedicated servers for multiplayer games, I ran into a very real problem: server-side entities needed rich, structured, and consistent AI behavior. In single-player games, the client usually handles this. In modern multiplayer titles with authoritative servers, the AI must run server-side — and that completely changes the performance and architectural demands.&lt;/p&gt;

&lt;p&gt;Behavior Trees were the obvious choice. I fell in love with &lt;strong&gt;Mistreevous&lt;/strong&gt;, a beautifully designed TypeScript library by &lt;em&gt;nikkorn&lt;/em&gt;, thanks to its clean, modular, and highly expressive DSL. The challenge? Bring that same elegance to the .NET world — but optimized for the harsh reality of server tick loops.&lt;/p&gt;

&lt;p&gt;This post is the story of that port: &lt;strong&gt;MistreevousSharp&lt;/strong&gt;, a ground-up rewrite focused on zero-allocation, predictability, and raw performance.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why Behavior Trees?
&lt;/h3&gt;

&lt;p&gt;Behavior Trees shine in games, robotics, simulations, and any agent-based system because they offer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hierarchical composition&lt;/li&gt;
&lt;li&gt;Excellent readability and intent clarity&lt;/li&gt;
&lt;li&gt;Strong modularity&lt;/li&gt;
&lt;li&gt;Easy debugging&lt;/li&gt;
&lt;li&gt;Predictable execution order&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For multiplayer servers specifically, they deliver:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extremely low cost per tick&lt;/li&gt;
&lt;li&gt;Deterministic outcomes&lt;/li&gt;
&lt;li&gt;Clean separation of logic and state&lt;/li&gt;
&lt;li&gt;Horizontal scaling across hundreds of entities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mistreevous already nailed the design in TypeScript. The C# version had to be just as expressive — but &lt;strong&gt;truly server-ready&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why Mistreevous Specifically?
&lt;/h3&gt;

&lt;p&gt;The original Mistreevous stands out with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A fluid, readable DSL&lt;/li&gt;
&lt;li&gt;Well-defined node types&lt;/li&gt;
&lt;li&gt;Simple parsing&lt;/li&gt;
&lt;li&gt;Full JSON compatibility&lt;/li&gt;
&lt;li&gt;An intuitive API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But it was built for a JavaScript runtime. In .NET (especially .NET 9 and .NET Standard 2.1), we have far more control over memory and performance.&lt;/p&gt;

&lt;p&gt;The goal: keep the spirit and compatibility, but eliminate allocations and make it scream on the server.&lt;/p&gt;




&lt;h3&gt;
  
  
  Not Just a Port — A Performance-Focused Rewrite
&lt;/h3&gt;

&lt;p&gt;While staying 100% semantically compatible with the original, almost every internal detail was re-engineered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zero-Allocation: The Core Principle
&lt;/h3&gt;

&lt;p&gt;The primary objective was simple: calling &lt;code&gt;Step()&lt;/code&gt; (one AI tick) must generate &lt;strong&gt;zero garbage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On a server with dozens or hundreds of entities ticking 30–60 times per second, even tiny repeated allocations become a GC nightmare.&lt;/p&gt;

&lt;p&gt;Key techniques applied:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Eliminated LINQ in hot paths&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
No enumerators, closures, or temporary collections.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reusable buffers and pools&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Pre-allocated, thread-safe lists reused across ticks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manual Span-based parsing&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Character-by-character processing instead of &lt;code&gt;Split()&lt;/code&gt; or regex.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No captured closures&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Avoided delegate allocations wherever possible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Classic &lt;code&gt;for&lt;/code&gt; loops&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Bypassing enumerator overhead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compact node design&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Fixed arrays, lightweight structs, minimal fields.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Full DSL and JSON Compatibility
&lt;/h3&gt;

&lt;p&gt;A non-negotiable requirement: any tree from the original Mistreevous must work unchanged.&lt;/p&gt;

&lt;p&gt;Example DSL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;root {
    sequence {
        action [CheckHealth]
        selector {
            action [Flee]
            action [Fight]
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MistreevousSharp supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identical SUCCESS / FAILURE / RUNNING semantics&lt;/li&gt;
&lt;li&gt;Same guard evaluation&lt;/li&gt;
&lt;li&gt;Subtree references&lt;/li&gt;
&lt;li&gt;Decorator behavior&lt;/li&gt;
&lt;li&gt;Execution order&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can literally copy-paste trees between TypeScript and C# projects.&lt;/p&gt;




&lt;h3&gt;
  
  
  Project Architecture Overview
&lt;/h3&gt;

&lt;p&gt;The repository is organized to mirror the conceptual structure while making optimizations explicit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MistreevousSharp/
├── assets/                      → Images and thumbnails
├── example/                     → Full working demo (MyAgent + Program.cs)
├── src/Mistreevous/
│   ├── Agent.cs
│   ├── BehaviourTree.cs         → Core execution engine
│   ├── BehaviourTreeBuilder.cs
│   ├── MDSLDefinitionParser.cs  → Zero-alloc DSL parser
│   ├── Nodes/                   → Full node hierarchy
│   │   ├── Composite/ (Sequence, Selector, Parallel, etc.)
│   │   ├── Decorator/ (Repeat, Retry, Flip, etc.)
│   │   └── Leaf/ (Action, Condition, Wait)
│   ├── Attributes/              → Guards and callbacks
│   └── Optimizations/           → Zero-allocation helpers
├── .github/workflows/           → Automated NuGet publish
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;Optimizations/&lt;/strong&gt; folder is unique to the C# version — it centralizes all performance-critical tricks that don't exist in the TS original.&lt;/p&gt;




&lt;h3&gt;
  
  
  Rough Performance Comparison
&lt;/h3&gt;

&lt;p&gt;Early benchmarks on modest trees:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Original Mistreevous (TS)&lt;/th&gt;
&lt;th&gt;MistreevousSharp (C#)&lt;/th&gt;
&lt;th&gt;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DSL Parsing&lt;/td&gt;
&lt;td&gt;~0.8 ms&lt;/td&gt;
&lt;td&gt;~0.35 ms&lt;/td&gt;
&lt;td&gt;~2.3× faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-tick execution&lt;/td&gt;
&lt;td&gt;Variable (GC pauses)&lt;/td&gt;
&lt;td&gt;Stable ~0.00x ms&lt;/td&gt;
&lt;td&gt;Near-zero overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Allocations per tick&lt;/td&gt;
&lt;td&gt;Multiple objects&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Zero&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Completely eliminated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The real gains scale dramatically with entity count.&lt;/p&gt;




&lt;h3&gt;
  
  
  Usage Example in C
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;definition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;@"
root {
    sequence {
        action [CheckHealth]
        selector {
            action [Flee]
            action [Fight]
        }
    }
}"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MyAgent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Implements your action callbacks&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BehaviourTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameIsRunning&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Step&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// One AI tick — zero allocations&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the full example in the repo's &lt;code&gt;example/&lt;/code&gt; folder.&lt;/p&gt;




&lt;h3&gt;
  
  
  Where It Shines
&lt;/h3&gt;

&lt;p&gt;Beyond multiplayer servers, MistreevousSharp is perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unity games (no GC spikes)&lt;/li&gt;
&lt;li&gt;Godot C# projects&lt;/li&gt;
&lt;li&gt;Simulations and autonomous agents&lt;/li&gt;
&lt;li&gt;Robotics and drone control&lt;/li&gt;
&lt;li&gt;Any system needing modular, readable AI&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Porting Mistreevous to C# was far more than translation — it required rethinking every allocation, every loop, and every object for the .NET reality. The result is a library that keeps the original's elegance and compatibility while being truly ready for high-performance, server-scale scenarios.&lt;/p&gt;

&lt;p&gt;If you're building anything with complex agent behavior in .NET, give it a try!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/guinhx/MistreevousSharp" rel="noopener noreferrer"&gt;https://github.com/guinhx/MistreevousSharp&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;NuGet:&lt;/strong&gt; &lt;a href="https://www.nuget.org/packages/MistreevousSharp" rel="noopener noreferrer"&gt;https://www.nuget.org/packages/MistreevousSharp&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Original Mistreevous (TS):&lt;/strong&gt; &lt;a href="https://github.com/nikkorn/mistreevous" rel="noopener noreferrer"&gt;https://github.com/nikkorn/mistreevous&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback, stars, and contributions very welcome! Let me know if you've used behavior trees on the server side — what pains did you hit?&lt;/p&gt;

&lt;p&gt;Tags: #dotnet #csharp #gamedev #behaviortrees #performance #opensource #multiplayer&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>gamedev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>NimbleMock: A Modern, Blazing-Fast Mocking Library for .NET (34x Faster Than Moq)</title>
      <dc:creator>Diego Teles</dc:creator>
      <pubDate>Sat, 13 Dec 2025 23:57:59 +0000</pubDate>
      <link>https://dev.to/guinhx/nimblemock-a-modern-blazing-fast-mocking-library-for-net-34x-faster-than-moq-5769</link>
      <guid>https://dev.to/guinhx/nimblemock-a-modern-blazing-fast-mocking-library-for-net-34x-faster-than-moq-5769</guid>
      <description>&lt;h1&gt;
  
  
  NimbleMock: A Modern, Blazing-Fast Mocking Library for .NET (34x Faster Than Moq)
&lt;/h1&gt;

&lt;p&gt;Hey devs! If you've ever felt the pain of verbose mocking setups, runtime overhead slowing down your test suites, or struggling to mock static methods like &lt;code&gt;DateTime.Now&lt;/code&gt; without ugly wrappers, you're not alone. Traditional libraries like Moq and NSubstitute are great, but in large-scale .NET projects (especially with async-heavy code and generic repositories), they can feel dated and slow.&lt;/p&gt;

&lt;p&gt;That's why I built &lt;strong&gt;NimbleMock&lt;/strong&gt; — a zero-allocation, source-generated mocking library designed for modern .NET testing in 2025 and beyond.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why I Built NimbleMock
&lt;/h3&gt;

&lt;p&gt;Over the years, I've dealt with common mocking frustrations in enterprise .NET apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Verbose setups&lt;/strong&gt; for large interfaces (mocking 20+ methods just to test one).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance hits&lt;/strong&gt; from runtime proxies (Castle.DynamicProxy in Moq) — slow creation and verification in big test suites.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static/sealed mocking hell&lt;/strong&gt; — no native support without paid tools or wrappers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Async and generics issues&lt;/strong&gt; — unexpected null tasks or clunky type inference.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brittle tests&lt;/strong&gt; — mocks that pass locally but fail in production because they don't match real API shapes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Moq is battle-tested (and had its share of drama), NSubstitute is clean and readable, but neither fully leverages modern .NET features like source generators for zero overhead.&lt;/p&gt;

&lt;p&gt;NimbleMock fixes these with compile-time magic: no runtime proxies, aggressive inlining, and stack allocation. Result? &lt;strong&gt;34x faster mock creation&lt;/strong&gt; and &lt;strong&gt;3x faster verification&lt;/strong&gt; than Moq, with zero allocations in typical scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Partial mocks&lt;/strong&gt;: Only mock what you need — unmocked methods throw clear &lt;code&gt;NotImplementedException&lt;/code&gt; for early detection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native static/sealed mocking&lt;/strong&gt;: Mock &lt;code&gt;DateTime.Now&lt;/code&gt;, &lt;code&gt;Environment&lt;/code&gt;, etc., directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First-class async support&lt;/strong&gt;: Seamless for &lt;code&gt;Task&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code&gt;ValueTask&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generic type inference&lt;/strong&gt;: Full support for nested generics (e.g., EF Core &lt;code&gt;IQueryable&amp;lt;T&amp;gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fluent, chainable API&lt;/strong&gt;: Inspired by the best of NSubstitute and Moq.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lie-proofing&lt;/strong&gt;: Optional runtime validation against real staging APIs to catch outdated mock shapes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compile-time analyzers&lt;/strong&gt;: Catch errors early (e.g., warn if you forget &lt;code&gt;SetupAsync&lt;/code&gt; for async methods).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MIT-licensed, open-source, and ready for contributions!&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Start
&lt;/h3&gt;

&lt;p&gt;Install via NuGet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package NimbleMock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basic example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;NimbleMock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IUserRepository&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;SaveAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Of&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IUserRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Alice"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetupAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;!),&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Returns Alice&lt;/span&gt;

&lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;Once&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Partial mock&lt;/strong&gt; (perfect for god-interfaces):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Partial&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ILargeService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Only&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;expectedData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Unmocked methods throw for safety&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Static mocking&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;staticMock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Static&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2025&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;staticMock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Once&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Generics example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;IQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Of&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsQueryable&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsActive&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Performance Benchmarks
&lt;/h3&gt;

&lt;p&gt;Run on .NET 8 (BenchmarkDotNet):&lt;/p&gt;

&lt;h4&gt;
  
  
  Mock Creation &amp;amp; Setup
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Time (ns)&lt;/th&gt;
&lt;th&gt;Memory Allocated&lt;/th&gt;
&lt;th&gt;Gain vs Moq&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Moq&lt;/td&gt;
&lt;td&gt;48,812&lt;/td&gt;
&lt;td&gt;10.37 KB&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NSubstitute&lt;/td&gt;
&lt;td&gt;9,937&lt;/td&gt;
&lt;td&gt;12.36 KB&lt;/td&gt;
&lt;td&gt;~5x faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NimbleMock&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1,415&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.45 KB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;34x faster&lt;/strong&gt; than Moq&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Method Execution Overhead
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Time (μs)&lt;/th&gt;
&lt;th&gt;Gain vs Moq&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Moq&lt;/td&gt;
&lt;td&gt;~1.4&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NSubstitute&lt;/td&gt;
&lt;td&gt;~1.6&lt;/td&gt;
&lt;td&gt;Slower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NimbleMock&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~0.6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.3x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Verification
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Time (ns)&lt;/th&gt;
&lt;th&gt;Memory Allocated&lt;/th&gt;
&lt;th&gt;Gain vs Moq&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Moq&lt;/td&gt;
&lt;td&gt;1,795&lt;/td&gt;
&lt;td&gt;2.12 KB&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NSubstitute&lt;/td&gt;
&lt;td&gt;2,163&lt;/td&gt;
&lt;td&gt;2.82 KB&lt;/td&gt;
&lt;td&gt;Slower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NimbleMock&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;585&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.53 KB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;3x faster&lt;/strong&gt; than Moq&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Powered by source generators — no runtime reflection!&lt;/p&gt;

&lt;p&gt;Run them yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet run &lt;span class="nt"&gt;--project&lt;/span&gt; tests/NimbleMock.Benchmarks &lt;span class="nt"&gt;--configuration&lt;/span&gt; Release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Migrating from Moq/NSubstitute
&lt;/h3&gt;

&lt;p&gt;It's straightforward — fluent chains make it cleaner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From Moq:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Moq&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IUserRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;Returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// NimbleMock&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Of&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IUserRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verification is more readable too.&lt;/p&gt;

&lt;p&gt;Full migration guide in the repo!&lt;/p&gt;

&lt;h3&gt;
  
  
  Lie-Proofing: Avoid "Tests That Lie"
&lt;/h3&gt;

&lt;p&gt;Unique feature: Validate mocks against real endpoints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;LieProofing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AssertMatchesReal&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IApiService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://api.staging.example.com"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Log mismatches&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Catches drifting APIs before production outages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;NimbleMock is built for .NET 8/9+ era: fast, safe, and joyful TDD. If you're tired of slow suites or static mocking hacks, give it a try!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/guinhx/NimbleMock" rel="noopener noreferrer"&gt;https://github.com/guinhx/NimbleMock&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;NuGet: &lt;a href="https://www.nuget.org/packages/NimbleMock" rel="noopener noreferrer"&gt;https://www.nuget.org/packages/NimbleMock&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback welcome — what pains do you have with current mocking libs? Would you switch for native statics and this speed?&lt;/p&gt;

&lt;p&gt;Star if you like it, and let's make testing fun again! 🚀&lt;/p&gt;

&lt;p&gt;Tags: #dotnet #csharp #testing #tdd #opensource #mocking #performance&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>opensource</category>
      <category>tdd</category>
      <category>mocking</category>
    </item>
  </channel>
</rss>
