按钮内的调用功能以进行单元测试

时间:2019-03-10 00:26:32

标签: c# forms function unit-testing button

private void btnSave_Click(object sender, EventArgs e)
    {
        if(txtFirstName.Text.Trim() != "" && txtLastName.Text.Trim() != "" && txtContact.Text.Trim() != "")
        {
            Regex reg = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$"); //only accepting proper email
            Match match = reg.Match(txtEmail.Text.Trim());
            if (match.Success)
            { using (SqlConnection sqlCon = new SqlConnection(connectionString)) // connecting info to database
                {
                    sqlCon.Open();
                    SqlCommand sqlCmd = new SqlCommand("ContactAddorEdit", sqlCon);
                    sqlCmd.CommandType = CommandType.StoredProcedure;
                    sqlCmd.Parameters.AddWithValue("@PhoneBookID", PhoneBookID); //connecting each value to database
                    sqlCmd.Parameters.AddWithValue("@FirstName", txtFirstName.Text.Trim());
                    sqlCmd.Parameters.AddWithValue("@LastName", txtLastName.Text.Trim());
                    sqlCmd.Parameters.AddWithValue("@Contact", txtContact.Text.Trim());
                    sqlCmd.Parameters.AddWithValue("@Email", txtEmail.Text.Trim());
                    sqlCmd.Parameters.AddWithValue("@Address", txtAddress.Text.Trim());
                    sqlCmd.ExecuteNonQuery(); // executeing the query in database
                    MessageBox.Show("Submitted successfully"); // showing message when success
                    Clear(); // clearing the form
                    GridFill();// refreshing the table
                }
            }
            else
            {
                MessageBox.Show(" Please enter a valid Email"); // Showing MEssage when email is not valid
            }
        }
        else
        {
            MessageBox.Show("Please fill Mandatory fields"); // if no input this message will show
        }

这些代码在表单的“保存”按钮下,我想在单元测试类中调用它们以进行测试。知道我该怎么办吗?谢谢

1 个答案:

答案 0 :(得分:0)

首先,恭喜您尝试找出如何编写单元测试。将代码隔离到可测试的单元中是一种习惯,会导致各种各样的好模式。

关于如何设置这样的东西有很多想法,但是我要在这里介绍的是一些步骤,旨在隔离测试代码,而无需太多更改代码本身。

我不会止步于此-实际上,在阅读和学习更多之后不久,您可能会学到一些更好的技术。我觉得有必要指出这一点,因为我在这里描述的只是一步,而不是最终的目的地。

首先,您可以将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代码的测试不是单元测试,因为它与您的数据库通信。这是一个集成测试。但是它的外观和功能就像单元测试一样。你要去

  • 安排-设置一些东西
  • 采取行动-执行您的方法
  • 声明-如果您期望的事情发生,则测试通过,否则失败。

对于真正简单的测试,您可以

  • 安排-从表中删除与某些模式匹配的所有记录,例如电子邮件地址为“ integrationtest@integrationtest.com”等。
  • 操作-调用您的方法,并传入一组值,包括刚删除的电子邮件地址。
  • 声明-查询数据库以确认它包含与您刚刚插入的值匹配的记录。
  • 清理-为了很好,请再次运行删除操作,以免留下测试记录。

要使插入和删除操作更容易,您可以将一个类放入您的单元测试项目中,如下所示:

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,并且已经在考虑单元测试,那就无所不能了。


Here's a blog post几年前,我写了这个。感觉过时了。对于一年多或两年前我写过的任何东西,我都感到很抱歉。