Extends Verify to allow verification of SqlServer bits.
See Milestones for release notes.
Entity Framework Extensions is a major sponsor and is proud to contribute to the development this project.
[ModuleInitializer]
public static void Init() =>
VerifySqlServer.Initialize();This test:
await Verify(connection);Will result in the following verified file:
await Verify(connection)
// include only tables and views
.SchemaIncludes(DbObjects.Tables | DbObjects.Views);Available values:
namespace VerifyTests.SqlServer;
[Flags]
public enum DbObjects
{
StoredProcedures = 1,
Synonyms = 2,
Tables = 4,
UserDefinedFunctions = 8,
Views = 16,
All = StoredProcedures | Synonyms | Tables | UserDefinedFunctions | Views
}Objects can be dynamically filtered:
await Verify(connection)
// include tables & views, or named MyTrigger
.SchemaFilter(
_ => _ is TableViewBase ||
_.Name == "MyTrigger");Recording allows all commands executed to be captured and then (optionally) verified.
Call Recording.Start():
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
Recording.Start();
await using var command = connection.CreateCommand();
command.CommandText = "select Value from MyTable";
var value = await command.ExecuteScalarAsync();
await Verify(value!);Will result in the following verified file:
{
target: 42,
sql: {
Text:
select Value
from MyTable,
HasTransaction: false
}
}Sql entries can be explicitly read using Recording.Stop(), optionally filtered, and passed to Verify:
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
Recording.Start();
await using var command = connection.CreateCommand();
command.CommandText = "select Value from MyTable";
var value = await command.ExecuteScalarAsync();
await using var errorCommand = connection.CreateCommand();
errorCommand.CommandText = "select Value from BadTable";
try
{
await errorCommand.ExecuteScalarAsync();
}
catch
{
}
var entries = Recording
.Stop()
.Select(_ => _.Data);
//Optionally filter results
await Verify(
new
{
value,
sqlEntries = entries
});Recording results can be interpreted in a variety of ways:
var entries = Recording.Stop();
// all sql entries via key
var sqlEntries = entries
.Where(_ => _.Name == "sql")
.Select(_ => _.Data);
// successful Commands via Type
var sqlCommandsViaType = entries
.Select(_ => _.Data)
.OfType<SqlCommand>();
// failed Commands via Type
var sqlErrorsViaType = entries
.Select(_ => _.Data)
.OfType<ErrorEntry>();Recording is enabled by VerifySqlServer.Initialize(), which subscribes to the Microsoft.Data.SqlClient diagnostic listener. Pass recordCommands: false to leave that listener unsubscribed:
[ModuleInitializer]
public static void Init() =>
VerifySqlServer.Initialize(recordCommands: false);Only recording is disabled. The converters, and the SqlConnection schema file converter, are still registered.
This is useful when another package records the same commands. Verify.EntityFramework records EF Core commands under the name ef, and EF Core executes those commands through SqlCommand. So with both packages recording, every command EF executes is captured twice: once as sql and once as ef.
Two constraints are worth knowing:
VerifierSettings.InitializePlugins()discovers this package and callsInitialize(), which enables recording. SoInitialize(recordCommands: false)has to run beforeInitializePlugins(), otherwise discovery initializes first and the explicit call throwsAlready Initialized.Recording.IgnoreNames("sql")is an alternative that needs no ordering, since it can be called at any point before recording starts. It discardssqlentries as they are added, but the listener stays subscribed, so each command is still cloned and then thrown away.
Database designed by Creative Stall from The Noun Project.

