我正确使用单元测试吗?

时间:2011-04-28 08:39:39

标签: c# .net unit-testing

这是我第一次编写TestMethod。我是否正确使用单元测试?

[TestMethod]
public void TestUpdateAccount()
{
    GwIntegrationServiceSoapClient client = new GwIntegrationServiceSoapClient();

    int id = 21; // Target account to update.
    Account accountToUpdate = client.ReadAccount(id);

    string oldName = accountToUpdate.Name;
    string oldEmail = accountToUpdate.Email;
    string newName = Guid.NewGuid().ToString();
    string newEmail = Guid.NewGuid().ToString() + "@nomail.com";

    // Update the name only, even a value is passed in newEmail 
    // But in the propertiesToUpdate parameter (last one) only Name value is passed.
    // Note: the UpdateAccountProperty could be: 
    //          [UpdateAccountProperty.Name | UpdateAccountProperty.Name.Email]
    client.UpdateAccount(id, newName, newEmail, null, false, UpdateAccountProperty.Name);

    // Read the record after updating from database
    Account updatedAccountFirstTime = client.ReadAccount(21);

    // The name should be changed
    Assert.AreEqual(newName, updatedAccountFirstTime.Name);

    // The email should not be changed
    Assert.AreNotEqual(newEmail, updatedAccountFirstTime.Email);

    ////////////////////////////////////////////////////////////
    // Now, after updating the name and everything is working well
    // Returning the old name to the record.
    client.UpdateAccount(id, oldName, oldEmail, null, false, UpdateAccountProperty.Name);

    // Read the record after updating
    Account updatedAccountSecondTime = client.ReadAccount(21);

    Assert.AreEqual(oldName, updatedAccountSecondTime.Name);
}

非常感谢您的回答。我已将测试方法更新为这两种方法:

[TestMethod]
public void UpdateAccount_OneValueExpectedToBeUpdated_Updated()
{
    GwIntegrationServiceSoapClient client = new GwIntegrationServiceSoapClient();

    int id = 21; // Target account to update.
    Account accountToUpdate = client.ReadAccount(id);

    string oldName = accountToUpdate.Name;
    string oldEmail = accountToUpdate.Email;
    string newName = Guid.NewGuid().ToString();

    // Update the name only because it's passed by propertiesToUpdate parameter (last one).
    client.UpdateAccount(id, newName, null, null, false, UpdateAccountProperty.Name);

    // Read the record after updating from database
    Account updatedAccountFirstTime = client.ReadAccount(id);

    // The name should be changed
    Assert.AreEqual(newName, updatedAccountFirstTime.Name);
}

[TestMethod]
public void UpdateAccount_NoValueExpectedToBeUpdated_NotUpdated()
{
    GwIntegrationServiceSoapClient client = new GwIntegrationServiceSoapClient();

    int id = 21; // Target account to update.
    Account accountToUpdate = client.ReadAccount(id);

    string oldName = accountToUpdate.Name;
    string oldEmail = accountToUpdate.Email;
    string newName = Guid.NewGuid().ToString();
    string newEmail = Guid.NewGuid().ToString() + "@nomail.com";

    // Update the name only, even a value is passed in newEmail 
    // But in the propertiesToUpdate parameter (last one) only Name value is passed.
    client.UpdateAccount(id, newName, newEmail, null, false, UpdateAccountProperty.Name);

    // Read the record after updating from database
    Account updatedAccountFirstTime = client.ReadAccount(id);

    // The email should not be changed
    Assert.AreNotEqual(newEmail, updatedAccountFirstTime.Email);
}

4 个答案:

答案 0 :(得分:5)

这很难回答,因为您将在“单元测试”标题下找到的测试类型会有所不同。大多数情况下,“单元测试”被用作“自动代码测试”的同义词,严格来说,它是通过编写代码以某种自动方式测试代码的任何东西。

如果您想编写良好单元测试,则只需遵循一些规则:

  • 独立测试场景。
  • 独立测试对象。<​​/ li>
  • 让您的测试保持小巧且专注。如果它们膨胀,请创建方法以帮助减少样板代码并专注于测试的细节。

最终,每次测试测试一件事。这样,当一个特定的行为或场景中断时,您可以立即关注对象的哪个特定部分失败。在您的示例中,您似乎在单个方法中测试了许多内容,如果第一次调用UpdateAccount成功,但第二次调用失败,则整个测试失败并且您不清楚哪个部分对象失败了。

答案 1 :(得分:3)

您应该获得The art of unit testing的副本。

有些要点:

  • 每次测试只有一次断言。
  • 测试方法的命名约定:public void MethodUnderTest_Scenario_Behavior()

答案 2 :(得分:1)

看起来不错。我的测试通常会减少行数。

是否可以将某些样板移动到夹具中?

答案 3 :(得分:1)

有些人(包括Roy Osherove在他的单元测试艺术中)推荐每个单元测试一个断言,看到好像第一个断言失败,抛出异常并且没有剩余的代码被调用而且没有其他断言被检查。

这可以分成两个或更多单元测试来实现这一点,例如一个用于在更新后检查名称,一个用于检查电子邮件地址,另一个用于检查更改和更改后的工作。