Hiện tại, phương pháp đang kiểm tra nó quá chặt chẽ cùng với những lo ngại về việc triển khai để làm cho nó dễ dàng có thể kiểm tra đơn vị một cách cô lập. Hãy thử tóm tắt các mối quan tâm về triển khai đó để chúng có thể dễ dàng bị chế nhạo cho các thử nghiệm riêng biệt.
public interface IDbConnectionFactory {
IDbConnection CreateConnection();
}
Phần tóm tắt của nhà máy kết nối ở trên có thể được sử dụng để truy cập System.Data
cần thiết khác phần tóm tắt của kho dữ liệu MySql của bạn.
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.
}
}
}
}
Việc triển khai sản xuất của nhà máy sẽ trả về một MySqlConnection
thực tế
public class MySqlConnectionFactory: IDbConnectionFactory {
public IDbConnection CreateConnection() {
return new MySqlConnection("connection string");
}
}
có thể được chuyển vào lớp dữ liệu thông qua chèn phụ thuộc
Để kiểm tra, bạn mô phỏng các giao diện bằng cách sử dụng khuôn khổ chế tạo mà bạn lựa chọn hoặc tạo ra các giao diện giả mạo của riêng bạn để đưa vào và kiểm tra phương pháp của bạn.
[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();
}
}
Cuối cùng, bạn nên sử dụng các tham số lệnh trong văn bản lệnh khi xây dựng chuỗi truy vấn mở mã theo cách thủ công trước các cuộc tấn công chèn SQL.
Để hiểu rõ hơn về cách sử dụng Moq, hãy xem Khởi động nhanh của họ