Во-первых, поздравляю с попыткой выяснить, как писать модульные тесты.Изоляция кода в тестируемые модули - это привычка, которая приводит ко всем видам отличных шаблонов.
Есть много идей о том, как мы могли бы создать что-то подобное, но все, что я собираюсь здесь изложить, - это некоторые шаги в направлении изоляции кода для тестирования без значительного изменения самого кода.
Я бы не стал останавливаться на этом - на самом деле, через короткое время после прочтения и изучения вы, вероятно, подберете еще более совершенные техники.Я чувствую необходимость указать на это, потому что то, что я описываю здесь, является шагом, а не конечным пунктом назначения.
Во-первых, вы можете переместить свой код SQL в класс, подобный этому:
public class SqlCommands
{
private readonly string _connectionString;
public SqlCommands(string connectionString)
{
_connectionString = connectionString;
}
public void InsertUpdateContact(InsertUpdateContactParameters parameters)
{
using (SqlConnection sqlCon = new SqlConnection(_connectionString))
{
sqlCon.Open();
SqlCommand sqlCmd = new SqlCommand("ContactAddorEdit", sqlCon);
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("@PhoneBookID", parameters.PhoneBookId); //connecting each value to database
sqlCmd.Parameters.AddWithValue("@FirstName",parameters.FirstName);
sqlCmd.Parameters.AddWithValue("@LastName",parameters.LastName);
sqlCmd.Parameters.AddWithValue("@Contact",parameters.Contact);
sqlCmd.Parameters.AddWithValue("@Email", parameters.Email);
sqlCmd.Parameters.AddWithValue("@Address",parameters.Address);
sqlCmd.ExecuteNonQuery();
}
}
}
public class InsertUpdateContactParameters
{
public int PhoneBookId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Contact { get; set; }
public string Email { get; set; }
public string Address { get; set; }
}
В качестве первого шага вы можете создать экземпляр класса SqlCommands
в своей форме, а затем вызвать InsertUpdateContact
, передав параметры, заполненные из полей формы.Это приводит вас к тому, что вы можете создавать тесты для своего кода SQL, которые вы можете выполнять без необходимости открывать форму, вводить значения и нажимать кнопку.
Тест для вашего кода SQL не выполняется 'Технически это юнит-тест, потому что он обращается к вашей базе данныхЭто интеграционный тест.Но это выглядит и функционирует так же, как юнит-тест.Вы собираетесь
- Упорядочить - настроить что-либо
- Действовать - выполнить свой метод
- Утвердить - ваш тест пройден, если то, что вы ожидаете, произойдет, иначене удается.
Для очень простого теста вы можете
- Упорядочить - удалить все записи из вашей таблицы, которые соответствуют некоторому шаблону, как, например, адрес электронной почты "integratest @ integratest.com "или тому подобное.
- Act - вызовите ваш метод, передав набор значений, включая тот же адрес электронной почты, который вы только что удалили.
- Assert - запросите в вашей базе данных подтверждениесодержит запись, совпадающую с только что введенными значениями.
- Очистка - для правильной меры запустите удаление еще раз, чтобы не оставить после себя запись тестирования.
Чтобы сделать вставкии удаления проще, вы могли бы поместить класс в ваш проект модульного теста что-то вроде этого:
static class Sql
{
public static void ExecuteSql(string connectionName, string sql)
{
using (var connection = new SqlConnection(GetConnectionString(connectionName)))
{
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
command.ExecuteNonQuery();
}
}
}
public static T ExecuteScalar<T>(string connectionName, string sql)
{
using (var connection = new SqlConnection(GetConnectionString(connectionName)))
{
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
return (T)command.ExecuteScalar();
}
}
}
public static string GetConnectionString(string connectionName)
{
return ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
}
}
Если вы используете .NET Framework, вы можете иметь файл app.config со строками подключения секПример:
<connectionStrings>
<add name="yourDatabaseName" connectionString="whatever your connection string is"
providerName="System.Data.SqlClient" />
</connectionStrings>
Или вы можете закодировать его, чтобы получить строку подключения в соответствии с тем, как вы ее храните.
Это позволяет вам писать код в ваших тестах, например
Sql.ExecuteSql("Your connection name", "SQL to delete records");
или
var numberOfInsertedRecords = Sql.ExecuteScalar<int>("Your connection name",
"SELECT COUNT(*) FROM Whatever WHERE ... "
+ "Replace with criteria that checks for the record you just inserted."
Тогда в своем тесте вы можете сказать:
Assert.AreEqual(1, numberOfInsertedRecords);
Некоторые другие интересные области, о которых вы хотели бы прочитать, это внедрение зависимостей, ORM (как Entity Framework и NHibernate) и CQRS.Это куча всего, что нужно, но если вы только начинаете писать форму и немного SQL, и уже думаете о модульных тестах, тогда предел - предел.
Вот пост в блоге Я писал об этом несколько лет назад.Это чувствует себя устаревшим.Я чувствую себя обязанным извиниться за все, что написал более года или двух.