Actuellement, la méthode testée est trop étroitement liée aux problèmes de mise en œuvre pour la rendre facilement testable à l'unité de manière isolée. Essayez d'abstraire ces problèmes de mise en œuvre afin qu'ils puissent être facilement simulés pour des tests isolés.
public interface IDbConnectionFactory {
IDbConnection CreateConnection();
}
L'abstraction de fabrique de connexions ci-dessus peut être utilisée pour accéder aux autres System.Data
nécessaires abstractions de votre magasin de données 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'implémentation de production de l'usine renverra un réel MySqlConnection
public class MySqlConnectionFactory: IDbConnectionFactory {
public IDbConnection CreateConnection() {
return new MySqlConnection("connection string");
}
}
qui peut être transmis à la couche de données via l'injection de dépendance
Pour tester, vous simulez les interfaces en utilisant le cadre de simulation de votre choix ou créez vos propres faux pour injecter et tester votre méthode.
[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();
}
}
Enfin, il est conseillé d'utiliser des paramètres de commande dans le texte de la commande, car la construction manuelle de la chaîne de requête ouvre le code aux attaques par injection SQL.
Pour mieux comprendre comment utiliser Moq, consultez leur Quickstart