Mysql
 sql >> Database >  >> RDS >> Mysql

Query di inserimento beffardo su un database MySQL utilizzando Moq

Attualmente il metodo in esame è troppo strettamente accoppiato alle preoccupazioni di implementazione per renderlo facilmente testabile in unità isolata. Prova ad astrarre questi problemi di implementazione in modo che possano essere facilmente presi in giro per test isolati.

public interface IDbConnectionFactory {
    IDbConnection CreateConnection();
}

L'astrazione della fabbrica di connessione sopra può essere utilizzata per accedere agli altri System.Data necessari astrazioni del tuo archivio dati 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.
            }
        }
    }
}

L'implementazione di produzione della fabbrica restituirà un effettivo MySqlConnection

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

che può essere passato al livello dati tramite iniezione di dipendenza

Per testare, prendi in giro le interfacce usando il tuo framework beffardo preferito o crei i tuoi falsi per iniettare e testare il tuo metodo.

[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();
    }
}

Infine è consigliabile utilizzare i parametri del comando nel testo del comando poiché la costruzione della stringa di query apre manualmente il codice agli attacchi di SQL injection.

Per capire meglio come usare Moq, controlla il loro Quickstart