SQL Server
El SqlServerContainer
es un componente de la librería CodeDesignPlus.Net.xUnit que proporciona un contenedor Docker para ejecutar SQL Server, una base de datos relacional. Este componente facilita la creación de pruebas unitarias que dependen de SQL Server, ofreciendo un entorno de pruebas aislado y reproducible.
¿Cómo Funciona?
El SqlServerContainer
utiliza Docker Compose
para definir y gestionar el contenedor SQL Server. Al inicializar una instancia de esta clase, se genera un archivo docker-compose.yml
temporal con la configuración necesaria para ejecutar el contenedor. Luego, el contenedor se inicia y se detiene automáticamente al final de la ejecución de las pruebas.
El proceso general de funcionamiento es el siguiente:
- Configuración del Contenedor: El método
Build()
define la configuración específica del contenedor SQL Server, incluyendo la ruta al archivodocker-compose.yml
, opciones de reinicio forzado, eliminación de contenedores huérfanos, parada al finalizar y un nombre de servicio alternativo generado dinámicamente para evitar conflictos. - Creación del Contenedor: Se crea una instancia de
DockerComposeCompositeService
usando la configuración definida. - Inicio y Detención del Contenedor: El contenedor se inicia cuando se crea una instancia de la clase
SqlServerContainer
y se detiene automáticamente cuando la instancia se elimina, asegurando la limpieza del entorno. - Configuración de Protocolo TLS: Establece el protocolo de seguridad
TLS 1.2
para la conexión al servidor SQL.
Container
El SqlServerContainer
hereda de la clase DockerCompose
, la cual proporciona la lógica base para interactuar con Docker Compose. La clase utiliza la clase DockerComposeCompositeService
de la librería Testcontainers
para iniciar y detener contenedores docker. La configuración del contenedor se define en el método Build()
que crea un archivo docker-compose.yml
con los parámetros necesarios para la ejecución del contenedor SQL Server. El archivo docker-compose.yml
se encuentra dentro del directorio Containers/SqlServer
.
namespace CodeDesignPlus.Net.xUnit.Containers.SqlServer;
/// <summary>/// Represents a Docker container for SQL Server, managed using Docker Compose./// </summary>public class SqlServerContainer : DockerCompose{ /// <summary> /// Builds the Docker Compose service configuration for the SQL Server container. /// </summary> /// <returns>An <see cref="ICompositeService"/> representing the Docker Compose service.</returns> protected override ICompositeService Build() { // Define the path to the Docker Compose file. var file = Path.Combine(Directory.GetCurrentDirectory(), "Containers", "SqlServer", "docker-compose.yml");
// Configure the Docker Compose settings. var dockerCompose = new DockerComposeConfig { ComposeFilePath = new[] { file }, ForceRecreate = true, RemoveOrphans = true, StopOnDispose = true, AlternativeServiceName = "sql_" + Guid.NewGuid().ToString("N"), };
// Enable port retrieval and set the internal port and container name. this.EnableGetPort = true; this.InternalPort = 1433; this.ContainerName = $"{dockerCompose.AlternativeServiceName}-sqlserver";
// Create and return the Docker Compose service. var compose = new DockerComposeCompositeService(base.DockerHost, dockerCompose);
return compose; }}
La clase SqlCollectionFixture
se utiliza como un fixture de xUnit, que proporciona una forma de compartir el contenedor entre las pruebas de una colección.
using System.Net;
namespace CodeDesignPlus.Net.xUnit.Containers.SqlServer;
/// <summary>/// Provides a fixture for managing a SQL Server container during xUnit tests./// </summary>public sealed class SqlCollectionFixture : IDisposable{ /// <summary> /// The name of the collection for the SQL Server tests. /// </summary> public const string Collection = "SqlServer Collection";
/// <summary> /// Gets the SQL Server container instance. /// </summary> public SqlServerContainer Container { get; }
/// <summary> /// Initializes a new instance of the <see cref="SqlCollectionFixture"/> class. /// </summary> public SqlCollectionFixture() { this.Container = new SqlServerContainer();
// Wait for the SQL Server container to be fully initialized. Thread.Sleep(10000); }
/// <summary> /// Disposes the SQL Server container instance. /// </summary> public void Dispose() { this.Container.StopInstance(); }}
Ejemplo de Uso
Este ejemplo muestra cómo usar SqlServerContainer
para realizar pruebas de integración con SQL Server. La prueba establece una conexión a una instancia de SQL Server utilizando la cadena de conexión y el puerto proporcionado por el contenedor, ejecuta una consulta SQL para validar la conexión y verifica que el contenedor este corriendo, demostrando el uso de SqlServerContainer
para probar interacciones con la base de datos.
using System;using System.Net;using CodeDesignPlus.Net.xUnit.Containers.SqlServer;using Microsoft.Data.SqlClient;
namespace CodeDesignPlus.Net.xUnit.Test;
[Collection(SqlCollectionFixture.Collection)]public class SqlServerContainerTest(SqlCollectionFixture sqlCollectionFixture){ private readonly SqlServerContainer container = sqlCollectionFixture.Container;
[Fact] public void CheckConnectionService() { // Arrange var sqlConnection = new SqlConnection($"Server=localhost,{this.container.Port};Database=master;User Id=sa;Password=Temporal1;Encrypt=True;TrustServerCertificate=True");
// Act sqlConnection.Open();
var transaction = sqlConnection.BeginTransaction();
var command = sqlConnection.CreateCommand();
command.Transaction = transaction;
command.CommandText = "SELECT 1";
command.ExecuteNonQuery();
transaction.Commit();
sqlConnection.Close();
// Assert Assert.True(this.container.IsRunning); }}
using System;using CodeDesignPlus.Net.xUnit.Containers.SqlServer;
namespace CodeDesignPlus.Net.xUnit.Test.Definitions;
[CollectionDefinition(SqlCollectionFixture.Collection)]public class SqlCollectionDefinition : ICollectionFixture<SqlCollectionFixture>{}
Conclusiones
- El
SqlServerContainer
facilita la creación de pruebas unitarias que requieren una instancia de SQL Server. - Utiliza Docker Compose para la gestión del contenedor, proporcionando una forma sencilla de definir la configuración.
- La clase
SqlCollectionFixture
permite compartir un contenedor entre todas las pruebas de una misma colección. - El uso del
SqlServerContainer
mejora la reproducibilidad y el aislamiento de las pruebas unitarias. - El contenedor SQL Server se inicia automaticamente al comienzo de cada prueba y se detiene una vez termina, esto permite un ambiente de pruebas limpio.