Skip to content

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:

  1. Configuración del Contenedor: El método Build() define la configuración específica del contenedor SQL Server, incluyendo la ruta al archivo docker-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.
  2. Creación del Contenedor: Se crea una instancia de DockerComposeCompositeService usando la configuración definida.
  3. 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.
  4. 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);
}
}

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.

Referencias Adicionales