TestDataDefinitionFramework.Core 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package TestDataDefinitionFramework.Core --version 1.0.0
                    
NuGet\Install-Package TestDataDefinitionFramework.Core -Version 1.0.0
                    
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="TestDataDefinitionFramework.Core" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TestDataDefinitionFramework.Core" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="TestDataDefinitionFramework.Core" />
                    
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 TestDataDefinitionFramework.Core --version 1.0.0
                    
#r "nuget: TestDataDefinitionFramework.Core, 1.0.0"
                    
#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.
#addin nuget:?package=TestDataDefinitionFramework.Core&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=TestDataDefinitionFramework.Core&version=1.0.0
                    
Install as a Cake Tool

TestDataDefinitionFramework

TestDataDefinitionFramework (or TDDF for short) is a library that abstracts the setup of test data from the implementation of data backing stores, so that the same test code can be run against both an in-memory/fake repository or a "real" repository using only pre-compiler conditionals to switch between the two.

An immediate design limitation is that this method will ONLY work when you are using "dumb data stores", so if you are running multi-table SQL queries or stored procedures, then this is not the library for you!

However, if your interactions with your data layer are usually that of "store this entity in this table", "query this entity from this table" then read on!

The Use Case

Ordinarily when writing integration tests (for example using SpecFlow) you will decide; "is this going to run against an in-memory fake, or against the "real" repository".

There are pros and cons to deciding on one: "in-memory" is fast and can run on the build server, but doesn't thoroughly test your data provider layer. Using "real" repositories more thoroughly tests your code layers as it proves the integration of your code with the chosen data storage engine, but is slower and requires connectivity to a running instance of your data storage engine of choice (e.g. a MongoDB or SQL instance).

Ideally it's nice to have both options, but a lot times this leads to a duplication of the integration test code - in SpecFlow terms the "step definitions" can look very different when you want to "setup" a MongoDB than when you only want to setup an in-memory context and pass that to an interceptor/fake repository.

The idea of TDDF is that by setting your test data against the TestDataStore you can then use that same data in an in-memory repository as easily as enabling a "real" backing store and the TDDF plugins will take care of actually standing up the "real" data resource.

Getting Started

  • Clone the source code repository and build, or install packages via NuGet.
  • Add a reference to "TestDataDefinitionFramework.Core" into your "integration tests" project (for example your SpecFlow/NUnit project).
  • Choose which backing stores plugins you want to use (e.g. TestDataDefinitionFramework.MongoDB)
  • Wire-up the code:
  1. Configure and Initialize (do this before your tests run), e.g. in SpecFlow
[BeforeTestRun]
public static async Task Initialize()
{
    var mongoBackingStore = new MongoBackingStore("ExampleSutDB");
    TestDataStore.AddRepository<SummaryItem>(cfg =>
    {
        cfg.WithName(SummaryCollection.Name);
#if UseRealProvider
            cfg.WithBackingStore(mongoBackingStore);
#endif
    });

    await TestDataStore.InitializeAllAsync();
}
  1. Use the TestDataStore for your setting up your test data, e.g. in SpecFlow
[Given(@"the summaries repository returns '(.*)'")]
public void GivenTheSummariesRepositoryReturns(IReadOnlyList<string> items)
{
    TestDataStore.Repository<SummaryItem>(SummaryCollection.Name).Items = items.Select(i => new SummaryItem {Name = i}).ToArray();
}
  1. Add your in-memory repository fakes (for when running in-memory mode):
public class WebTestFixture : WebApplicationFactory<Startup>
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        base.ConfigureWebHost(builder);

        builder.UseEnvironment("Testing");

        builder.ConfigureTestServices(services =>
        {
#if !UseRealProvider
            services.AddTransient<ISummariesRepository, InMemorySummariesRepository>();
#endif
        });
    }
}
  1. Implement your in-memory repository:
public class InMemorySummariesRepository : ISummariesRepository
{
    public Task<IReadOnlyList<string>> GetAllAsync()
    {
        var result = TestDataStore.Repository<SummaryItem>(SummaryCollection.Name)
                            .Items?.Select(i => i.Name).ToArray()
            ?? Array.Empty<string>();

        return Task.FromResult((IReadOnlyList<string>) result);
    }
}
  1. Commit the test data before calling the SUT (the best way to acheive this in SpecFlow is to trigger before the "When" block)
[BeforeScenarioBlock]
public async Task Commit()
{
    if (_scenarioContext.CurrentScenarioBlock == ScenarioBlock.When)
    {
        await TestDataStore.CommitAllAsync();
    }
}

Now you can run your tests against an in-memory fake, or against a "real" repository by simply setting or unsetting a pre-compiler conditional called "UseRealProvider".

Notes

  • See the ExampleTests project for a working version of the above
Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on TestDataDefinitionFramework.Core:

Package Downloads
TestDataDefinitionFramework.MongoDB

MongoDB backing store extension for TestDataDefinitionFramework

TestDataDefinitionFramework.Sql

Sql backing store extension for TestDataDefinitionFramework

TestDataDefinitionFramework.Redis

Redis backing store extension for TestDataDefinitionFramework

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0 176 2/5/2024
2.0.2 364 5/15/2023
2.0.1 346 2/3/2023
2.0.0 646 1/31/2023
1.1.0 594 10/14/2021
1.0.0 478 8/20/2021