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

Mocking insert-forespørgsel til en MySQL-database ved hjælp af Moq

I øjeblikket er den metode, der testes, for tæt koblet til implementeringsproblemer til at gøre den let enhedstestbar i isolation. Prøv at abstrahere disse implementeringsproblemer, så de let kan hånes for isolerede tests.

public interface IDbConnectionFactory {
    IDbConnection CreateConnection();
}

Ovenstående forbindelsesfabriksabstraktion kan bruges til at få adgang til de andre nødvendige System.Data abstraktioner af dit MySql-datalager.

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.
            }
        }
    }
}

Produktionsimplementeringen af ​​fabrikken vil returnere en faktisk MySqlConnection

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

som kan overføres til datalaget via afhængighedsinjektion

For at teste håner du grænsefladerne ved at bruge din valgte hånende ramme eller laver dine egne forfalskninger for at injicere og teste din metode.

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

Endelig er det tilrådeligt, at du bruger kommandoparametre i kommandoteksten, da konstruktion af forespørgselsstrengen manuelt åbner koden op til SQL-injektionsangreb.

For bedre at forstå, hvordan man bruger Moq, tjek deres Quickstart




  1. Zend_Db:Hvordan opretter man forbindelse til en MySQL-database over SSH-tunnel?

  2. Hvordan kan jeg få antallet af rækker 'returneret' fra et resultatsæt af en lagret procedure

  3. Oracle-skemabruger kan ikke oprette tabel i procedure

  4. Postgres:Hvordan laver man sammensatte nøgler?