Nubbin 0.6.1

dotnet add package Nubbin --version 0.6.1
                    
NuGet\Install-Package Nubbin -Version 0.6.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Nubbin" Version="0.6.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nubbin" Version="0.6.1" />
                    
Directory.Packages.props
<PackageReference Include="Nubbin" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Nubbin --version 0.6.1
                    
#r "nuget: Nubbin, 0.6.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Nubbin@0.6.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Nubbin&version=0.6.1
                    
Install as a Cake Addin
#tool nuget:?package=Nubbin&version=0.6.1
                    
Install as a Cake Tool

Nubbin

Nubbin is a C# source generator that creates dummy implementations for partial classes marked with the Stub attribute.

What It Generates

The generator finds unimplemented members from:

  • Implemented interfaces
  • Abstract base classes
  • Classes that combine both

Generated methods use these return values:

  • void: an empty method body
  • Task: Task.CompletedTask
  • Task<T>: a completed task containing the generated default value
  • Non-nullable reference types without a supported default: NotImplementedException
  • Nullable reference types and other return types: default

The same logic to determine the type applies to out parameters.

Nullable reference-type defaults are null; value types use their normal default value. Non-nullable reference types use an accessible parameterless constructor when available, otherwise the generated member throws NotImplementedException. Collection interfaces receive empty compatible collections instead of null:

  • IEnumerable<T>, IReadOnlyCollection<T>, and IReadOnlyList<T>: an empty array
  • ICollection<T> and IList<T>: an empty List<T>
  • ISet<T>: an empty HashSet<T>
  • IDictionary<TKey, TValue> and IReadOnlyDictionary<TKey, TValue>: an empty Dictionary<TKey, TValue>
  • Non-generic IEnumerable, ICollection, and IList: an empty array or ArrayList

Properties are generated with the accessors required by their declaration. Interface properties always receive both a getter and setter. Abstract properties preserve their accessor shape, so getter-only and setter-only abstract properties remain valid overrides. Generated properties use regular auto-implemented properties whenever possible, with initial values following the same default rules as method returns. Abstract properties with only one accessor use a typed GetPropertyHelper() extension backed by a weak table, because C# does not allow the missing accessor to be added to an override. Each stub gets its own generated PropertyHelper storage type without adding a storage property or nested type to the original stub class. The generated extension container is named The generated extension methods are placed in a partial static Nubbin.Stubs helper class, avoiding conflicts with members named Properties or PropertyAccessor. Each typed property helper is placed in the stub namespace's .Nubbin child namespace.

Existing implementations are preserved. If an abstract base class and an interface declare the same member, only one implementation is generated.

Usage

Reference the Nubbin project or package from a consumer project. The target class must be partial because source generators add the implementation in a separate partial declaration.

Explicit stubs

using Nubbin;

public interface IClock
{
    DateTime Now();
}

[Stub]
public partial class TestClock : IClock
{
}

The generated TestClock.Now() returns default(DateTime).

Properties and collection return types are stubbed as follows:

public interface IReportClient
{
  IList<string> GetTags();
  string Name { get; set; }
}

[Stub]
public partial class TestReportClient : IReportClient
{
}

GetTags() returns an empty List<string>, and Name uses typed weak-table storage with a null initial value. The generated storage can be accessed with client.GetPropertyHelper() when direct inspection or setup is useful.

Auto stubs

When you only need a default implementation, call Stub.Auto<T>() from any partial type. The generator creates a nested Stub container that returns the matching generated stub instance for the requested interface or abstract base member type.

using Nubbin;

public interface ILogger {
  void Log(string message);
}

public partial class LoggerTest
{
    public void Test()
    {
        DoProcess(Stub.Auto<ILogger>());
    }

    private void DoProcess(ILogger logger)
    { }
}

This is intended for convenience scenarios where the generated stub only needs to provide default behavior and you do not want to define a dedicated stub type by hand.

Constraints

  • [Stub] applies to classes only.
  • The target class must be declared partial.
  • Generated implementations are intentionally minimal and do not contain production behavior.

Building and Testing

dotnet build Nubbin.slnx
dotnet test Nubbin.Test/Nubbin.Test.csproj

The generator and attribute are currently kept in the main Nubbin assembly.

Continuous Integration and Releases

The GitHub Actions workflow restores, builds, and tests pull requests targeting main. Release Please watches pushes to main, parses Conventional Commits, and opens or updates a release PR with the version and changelog changes. Merge that PR to create the GitHub release and tag. Every Release Please PR creation or update also builds and publishes an -rc.<run-number> package from the CI build output. Merging the Release Please PR creates the GitHub release and automatically publishes the tagged stable package.

Repository setup requires:

  • NuGet Trusted Publishing configured for this GitHub repository and both workflows. In nuget.org account settings, add GitHub Actions trusted publishing policies using this repository's owner and name. Enter only ci.yml for the workflow file in the RC policy and publish-release.yml in the stable policy; do not enter the .github/workflows/ path. Leave the environment field empty.
  • A NUGET_USERNAME repository secret containing the nuget.org profile name that owns the package, not an email address.
  • A RELEASE_PLEASE_TOKEN repository secret containing a PAT or GitHub App token that can create release PRs and trigger workflows from the created release.

Release Please calculates package versions from Conventional Commit messages:

  • fix: and other recognized changes increment the patch version.
  • feat: increments the minor version.
  • ! after the type/scope or a BREAKING CHANGE: footer increments the major version.

Stable releases are tagged as v<version> by Release Please. Merging the Release Please PR is the approval gate for both the version and NuGet publication.

License

Nubbin is available under the MIT License. See LICENSE.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.6.1 93 8/19/2026
0.6.1-rc.12 57 8/19/2026
0.6.1-rc.11 63 8/19/2026
0.6.0 92 8/18/2026
0.6.0-rc.10 63 8/18/2026
0.5.1 109 8/17/2026
0.5.1-rc.9 62 8/17/2026
0.5.0 102 8/16/2026
0.5.0-rc.8 67 8/16/2026
0.4.0 99 8/10/2026
0.4.0-rc.7 60 8/10/2026
0.3.0 93 8/10/2026
0.3.0-rc.6 59 8/10/2026
0.2.0 94 8/9/2026