This .NET library simplifies data mocking for UnitTests, to avoid a connection to a relational database. DbMocker use the standard Microsoft .NET DbConnection object. So, you can mock any toolkit, including EntityFramework, Dapper or ADO.NET; And for all database servers (SQL Server, Oracle, SQLite).
First, add the DbMocker NuGet packages.
Next, instanciate a MockDbConnection and mock you SQL requests using a condition and return a DataTable.
Please, contact me if you want other features or to solve bugs.
// Sample method from your DataService
public int GetNumberOfEmployees(DbConnection connection)
{
    using (var cmd = connection.CreateCommand())
    {
        cmd.CommandText = "SELECT COUNT(*) FROM Employees";
        return Convert.ToInt32(cmd.ExecuteScalar());
    }
}
/* Create a text file "123-EMPLOYEES.txt" with this content
   And set the build property to "Embedded resource".
        Id        Name          Age
        (int)     (string)      (int?)
        10        Scott         21
        20        Bill          NULL
*/
[TestMethod]
public void UnitTest0()
{
    var conn = new MockDbConnection();
    // The text file "123-EMPLOYEES.txt" is embedded in this project.
    // See the Samples folder.
    //  - 123       is an identifier (as you want)
    //  - EMPLOYEES is the CommandText Tag 
    //    See https://docs.microsoft.com/en-us/ef/core/querying/tags
    conn.Mocks.LoadTagsFromResources("123-EMPLOYEES");
    // Call your "classic" methods to tests
    var data = GetEmployees(conn);
    // DbMocker read the embedded file 
    // and associated the content to the tag
    Assert.AreEqual("Scott", data[0][1]);
    Assert.AreEqual("Bill", data[1][1]);
}
[TestMethod]
public void UnitTest1()
{
    var conn = new MockDbConnection();
    // When a specific SQL command is detected,
    // Don't execute the query to your database engine (SQL Server, Oracle, SQLite, ...),
    // But returns this _Table_.
    conn.Mocks
        .When(cmd => cmd.CommandText.StartsWith("SELECT") &&
                     cmd.Parameters.Count() == 0)
        .ReturnsTable(MockTable.WithColumns("Count")
                               .AddRow(14));
    // Call your "classic" methods to tests
    int count = GetNumberOfEmployees(conn);
    Assert.AreEqual(14, count);
}See DbMocker Wiki pages for more information.
Use the When method to describe the condition to be detected.
This condition is based on a Lambda expression containing a CommandText or Parameters check.
conn.Mocks
    .When(cmd => cmd.CommandText.StartsWith("SELECT") &&
                 cmd.Parameters.Count() == 0)
    .ReturnsTable(...);Use the WhenTag method to detect query containing a row starting with -- MyTag.
This is compatible with EFCore 2.2, containing a new extension method WithTag to identity a request.
conn.Mocks
    .WhenTag("MyTag")
    .ReturnsTable(...);Use WhenAny to detect all SQL queries. In this case, all queries to the database will return the data specified by WhenAny.
conn.Mocks
    .WhenAny()
    .ReturnsTable(...);When the previous condition occured, a mocked table will be return:
Creating an new instance of MockTable.
conn.Mocks
    .WhenAny()
    .ReturnsTable(new MockTable().AddColumns("ID", "Name")
                                 .AddRow(1, "Scott")
                                 .AddRow(2, "Bill"));Using a MockTable.Empty() table... to complete.
conn.Mocks
    .WhenAny()
    .ReturnsTable(MockTable.Empty()
                           .AddColumns("ID", "Name")
                           .AddRow(1, "Scott")
                           .AddRow(2, "Bill"));Using a MockTable.WithColumns() table... to complete.
conn.Mocks
    .WhenAny()
    .ReturnsTable(MockTable.WithColumns("ID", "Name")
                           .AddRow(1, "Scott")
                           .AddRow(2, "Bill"));Using a MockTable.WithColumns() typed columns. In this case, columns are defined using a tuple (ColumnName, ColumnType).
conn.Mocks
    .WhenAny()
    .ReturnsTable(MockTable.WithColumns(("ID", typeof(int?)),
                                        ("Name", typeof(string)))
                            .AddRow(null, "Scott")
                            .AddRow(2, "Bill"));Returning a MockTable.SingleCell() table... to complete.
conn.Mocks
    .WhenAny()
    .ReturnsTable(MockTable.SingleCell("Count", 14));Using an expression to customize the return.
conn.Mocks
    .WhenAny()
    .ReturnsTable(cmd => cmd.Parameters.Count() > 0 ? 14 : 99);using a CSV string with all data. The first row contains the column names. The first data row defines types for each columns (like in a Excel importation).
string csv = @" Id	Name	Birthdate
                1	Scott	1980-02-03
                2	Bill	1972-01-12
                3	Anders	1965-03-14 ";
conn.Mocks
    .WhenAny()
    .ReturnsTable(MockTable.FromCsv(csv));When a condition occured, a single data row will be return. The specified typed object will generate a MockTable where property names will be the column names and proerty values will be the first row data.
conn.Mocks
    .WhenAny()
    .ReturnsRow(new { Id = 1, Name = "Denis" });Using an expression to customize the return.
conn.Mocks
    .WhenAny()
    .ReturnsRow(cmd => new { Id = 1, Name = "Denis" });When a condition occured, a scalar value will be return:
conn.Mocks
    .WhenAny()
    .ReturnsScalar<int>(14);conn.Mocks
    .WhenAny()
    .ReturnsScalar<int>(cmd => DateTime.Today.Year > 2000 ? 14 : 0);Call the method Mocks.HasValidSqlServerCommandText()
to check if your string CommandText respect the SQL Server syntax...
without connection to SQL Server (but using the Microsoft.SqlServer.SqlParser package).
conn.Mocks
    .HasValidSqlServerCommandText()
    .WhenAny()
    .ReturnsScalar(14);So the CommandText="SELECT ** FROM EMP" (double )
will raised a MockException with the message "Incorrect syntax near ''".
You can also define a default value using the MockDbConnection.HasValidSqlServerCommandText property.
var conn = new MockDbConnection()
{
    HasValidSqlServerCommandText = true
};- #40 Add the Callback support to MockReturns with unit test. Thanks Tridy.
- #36 Accept white list of properties, with MockTable.FromTypemethod. Thanks zewa666.
- #35 MockDbDataReader.GetBytesdoes fill thebufferparam. Thanks Stepami.
- Dependencies updated.
- #32 Update MockDbDataReader.IsClosedThanks kiainlogicdk for the discussion.
- #31 Implement the DbDataReader.GetSchemaTable()method. Thanks javnov.
- #29 Fix Disposemethod to change the ConnectionState to Closed. Thanks OlegKrymskyi.
- #27 Fix ExecuteScalarmethod to respect the Microsoft documentation. "If the first column of the first row in the result set is not found, a null reference is returned. If the value in the database is null, the query returns DBNull.Value." Thanks Andreas.
- Use a direct reference to SqlParser.dll. Thanks yyalkovich.
- Add methods ThrowsException()to throw an exception when a condition has occured. Thanks wessonben.
- Fix consistent NewLine detection (\n, \r or both), used by WhenTagmethod. Thanks martinsmith1968.
- Add MockTable.FromType<T>method to fill a mock table using existing .NET objects. Thanks martinsmith1968.
- Fix MockDbDataReader.IsDBNullwhen the value is null.
- Add 'Guid' type in MockTable.FromFixedand resource sample files.
- Add a custom message when a sample conversion fails. Ex: Invalid conversion of "2020-01-32" to "DateTime", for column "Col1".
- Set output value for DbParameter, using MockResturns.SetParameterValuemethod. Thanks unby.
- Fix MockDbDataReader.HasRowsto return true when at least a row is existing. Thanks htw8441.
- Fix the fixed format (resource files) to convert values using Invariant Culture.
- Minor fixes to deploy nuget.
- Add MockResourceOptions.TagSeparator(default is '-') to allow to include multiple MockTable resource samples. "01-MyTag.txt" and "02-MyTag.txt" are two resource using the same SQL tag (MyTag).
- Add Mocks.LoadTagsFromResourcesto include MockTable samples described in Embedded resource text files.
- Add ReturnsDatasetmethods to simulate multiple tables (Thanks stop-cran).
- Update the reference to the Nuget Microsoft.SqlServer.Management.SqlParser to validate syntaxes of SQL queries.
- Add detailed SQL Query in MockException properties (#6).
- Add a new WhenTag method (#7).
- Add a method to validate the syntax of SQL queries without connection to SQL Server (only for SQL Server syntax) (#8).
- Add a MockColumnclass to manage the column type. See example using "typed columns" above.
- Breaking change: to allow typed MockColumn, the property MockTable.Columnsis now of type MockColumn[] (previously string[]).
- Add MockTable.FromCsv(string)method.
- Add ReturnsRow(T)andReturnsRow(Func<MockCommand, T>)methods.