Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Spöttisches Einfügen einer Abfrage in eine MySQL-Datenbank mit Moq

Derzeit ist die zu testende Methode zu eng an Implementierungsbelange gekoppelt, um sie auf einfache Weise isoliert testen zu können. Versuchen Sie, diese Implementierungsprobleme zu abstrahieren, damit sie für isolierte Tests leicht verspottet werden können.

public interface IDbConnectionFactory {
    IDbConnection CreateConnection();
}

Die obige Connection-Factory-Abstraktion kann verwendet werden, um auf die anderen notwendigen System.Data zuzugreifen Abstraktionen Ihres MySQL-Datenspeichers.

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

Die Produktionsimplementierung der Factory gibt eine tatsächliche MySqlConnection zurück

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

die per Dependency Injection in die Datenschicht übergeben werden können

Zum Testen mocken Sie die Schnittstellen mit Ihrem Mocking-Framework Ihrer Wahl nach oder erstellen Ihre eigenen Fälschungen, um Ihre Methode einzufügen und zu testen.

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

Schließlich ist es ratsam, dass Sie Befehlsparameter im Befehlstext verwenden, da das manuelle Erstellen der Abfragezeichenfolge den Code für SQL-Injection-Angriffe öffnet.

Um besser zu verstehen, wie man Moq verwendet, lesen Sie deren Quickstart