sql >> Base de Datos >  >> RDS >> Mysql

Consulta de inserción simulada en una base de datos MySQL usando Moq

Actualmente, el método que se está probando está demasiado estrechamente relacionado con las preocupaciones de implementación para que sea fácilmente comprobable por unidad de forma aislada. Intente abstraer esos problemas de implementación para que puedan burlarse fácilmente para pruebas aisladas.

public interface IDbConnectionFactory {
    IDbConnection CreateConnection();
}

La abstracción de la fábrica de conexiones anterior se puede utilizar para acceder a los otros System.Data necesarios abstracciones de su almacén de datos MySql.

public class MyDataAccessClass {
    private IDbConnectionFactory connectionFactory;

    public MyDataAccessClass(IDbConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    public void Insert(string firstname, string lastname) {
        var query = $"INSERT INTO `sakila`.`actor`(`first_name`,`last_name`) VALUES('" + firstname + "','" + lastname + "')";
        Console.WriteLine(query);
        using(var connection = connectionFactory.CreateConnection() {
            //Creates and returns a MySqlCommand object associated with the MySqlConnection. 
            using(var command = connection.CreateCommand()) {
                command.CommandText = query;
                Console.WriteLine("Established connection");
                connection.Open();
                command.ExecuteNonQuery();
                Console.WriteLine("Insert query succesfully executed.");
                connection.Close();//is not actually necessary as the using statement will make sure to close the connection.
            }
        }
    }
}

La implementación de producción de la fábrica devolverá un MySqlConnection real

public class MySqlConnectionFactory: IDbConnectionFactory {
    public IDbConnection CreateConnection() {
        return new MySqlConnection("connection string");
    }
}

que se puede pasar a la capa de datos a través de la inyección de dependencia

Para probar, simula las interfaces utilizando el marco de simulación de su elección o crea sus propias falsificaciones para inyectar y probar su método.

[TestClass]
public class DataAccessLayerUnitTest {
    [TestMethod]
    public void TestInsert() {
        //Arrange
        var commandMock = new Mock<IDbCommand>();
        commandMock
            .Setup(m => m.ExecuteNonQuery())
            .Verifiable();

        var connectionMock = new Mock<IDbConnection>();
        connectionMock
            .Setup(m => m.CreateCommand())
            .Returns(commandMock.Object);

        var connectionFactoryMock = new Mock<IDbConnectionFactory>();
        connectionFactoryMock
            .Setup(m => m.CreateConnection())
            .Returns(connectionMock.Object);

        var sut = new MyDataAccessClass(connectionFactoryMock.Object);
        var firstName = "John";
        var lastName = "Doe";

        //Act
        sut.Insert(firstName, lastName);

        //Assert
        commandMock.Verify();
    }
}

Finalmente, es recomendable que use parámetros de comando en el texto del comando, ya que la construcción de la cadena de consulta abre manualmente el código para ataques de inyección SQL.

Para comprender mejor cómo usar Moq, consulte su Quickstart