2017-03-14 2 views
3

Ich versuche derzeit, Mocking mit Moq zu lernen, und ich wollte es auf einer vorhandenen Datenbank, die ich habe, aber ich bin mir nicht sicher, wie ist der richtige Weg, dies zu nähern.Mocking einfügen Abfrage zu einer MySQL-Datenbank mit Moq

In meiner Datenschicht habe ich eine Klasse, die die Verbindung mit der DB handhabt und die verschiedenen Methoden zum Einfügen, Auswählen usw. hat. Ich möchte testen, ob ein Akteur korrekt in die Datenbank eingefügt wurde.

Meine Insert-Methode sieht derzeit wie folgt aus:

public void Insert(string firstname, string lastname) 
{ 
    string query = $"INSERT INTO `sakila`.`actor`(`first_name`,`last_name`) VALUES('" + firstname + "','" + lastname + "')"; 
    Console.WriteLine(query); 
    //open connection 
    if (this.OpenConnection() == true) 
    { 
     Console.WriteLine("Established connection"); 
     //create command and assign the query and connection from the constructor 
     MySqlCommand cmd = new MySqlCommand(query, connection); 

     //Execute command 
     cmd.ExecuteNonQuery(); 
     Console.WriteLine("Insert query succesfully executed."); 

     //close connection 
     this.CloseConnection(); 
    } 
} 

Wie würde ich mich über diese mit Mocks zu tun? Erstelle ich eine Klasse für die Akteureinheit? Soll ich eine Schnittstelle für meine Klasse DbConnection erstellen? Sorry für alle Fragen, aber ich bin wirklich ratlos, wie ich dieses Problem angehen kann.

Antwort

2

Gegenwärtig ist die zu testende Methode zu eng an die Implementierungsprobleme gebunden, um sie leicht einzeln testbar zu machen. Versuchen Sie, diese Bedenken hinsichtlich der Implementierung zu abstrahieren, damit sie leicht für isolierte Tests verspottet werden können.

public interface IDbConnectionFactory { 
    IDbConnection CreateConnection(); 
} 

Die Abstraktion über Connection Factory können die anderen notwendigen System.Data Abstraktionen Ihrer MySql Datenspeicher zugegriffen werden.

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 Produktion Umsetzung der Fabrik wird wieder eine tatsächliche MySqlConnection

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

die zur Prüfung verspotten Sie die Schnittstellen mit Ihrem Mockframework

über Dependency Injection in die Datenschicht übergeben werden können der Wahl oder erstellen Sie Ihre eigenen Fälschungen, um Ihre Methode zu injizieren 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 in der Befehlstext als den Aufbau der Query-String manuell öffnet den Code bis zu SQL-Injection-Angriffe nutzen.

Um besser zu verstehen, wie man Moq verwendet, überprüfen Sie ihre Quickstart