我是否在单元测试中编写正确的测试方法?

时间:2013-06-10 13:04:43

标签: asp.net-mvc-3 unit-testing

我正在开发MVC应用程序并编写单元测试。 我对单元测试的编码模式/过程感到困惑。 我正在编写单元测试,但我不知道,我是否以正确的方式写作。

我举一个测试用例的例子,请检查。

基本上,在测试方法中我写的是我在GetPartiesByEmployee()方法中编写的相同代码,我正在比较no。从方法返回的记录和从测试方法中的代码博客返回的记录是正确的吗?

这是对的吗?

  

[TestMethod的]

    public void Test_Get_Parties_By_Employee_Method()
    {

        var actualResult = oPartyHelper.GetPartiesByEmployee(6);
        Employee oEmployee = new Employee();
        oEmployee = db.Employees.Find(6);
        var roles = oEmployee.Roles.ToList();
        List<Party> parties = new List<Party>();
        foreach (Role item in roles)
        {
            var PartyCollection = from e in item.Parties.OrderBy(e => e.Name)
                                  where (e.IsDeleted == false || e.IsDeleted == null)
                                  select e;
            parties.AddRange(PartyCollection.ToList());               
        }
        parties=parties.Distinct().OrderBy(p => p.Id).ToList();
        var expectedCount = parties.Count();
        var actualList = (List<Party>)actualResult;
        var actualCount = actualList.Count;
        Assert.AreEqual(expectedCount, actualCount, "All parties are not same");
    }

实际方法:

public List<Party> GetPartiesByEmployee(int employeeId)
        {
            Employee oEmployee = new Employee();
            oEmployee = db.Employees.Find(employeeId);
            var roles = oEmployee.Roles.ToList();
            List<Party> parties = new List<Party>();
            foreach (Role item in roles)
            {
                var PartyCollection = from e in item.Parties.OrderBy(e => e.Name)
                                      where (e.IsDeleted == false || e.IsDeleted == null)
                                      select e;

                parties.AddRange(PartyCollection.ToList());

            }

            return parties.Distinct().OrderBy(p=>p.Id).ToList();             
        }

2 个答案:

答案 0 :(得分:4)

不,这不是单元测试的工作原理。您不会将相同的代码复制到测试方法中,而是测试具有代码的实际对象。 (只是复制代码不仅会创建奇怪且可能无用的测试,但它会复制系统中的所有,这是不可维护的。)

所以假设你有一个像这样的方法:

public int ActualMethod()
{
    var x = 0;
    var y = 1;
    return x + y;
}

您可以测试该代码:

[Test]
public void TestMethod()
{
    var x = 0;
    var y = 1;
    Assert.Equal(1, x + y);
}

你应该有类似的东西:

[Test]
public void TestMethod()
{
    var testableObject = new SomeObject();
    var expectedResult = 1;
    var actualResult = testableObject.ActualMethod();
    Assert.Equal(expectedResult, actualResult);
}

(您可以根据需要修改其可读性。我可能过于明确地使用该测试方法中的代码和变量名称,只是为了演示正在发生的事情。)

这个想法是单元测试加载正在测试的实际模块,而不是代码行的副本。从面向对象设计的封装角度考虑它。这些对象之外的任何内容包括测试本身都应该了解其内部实现。测试只是与对象进行交互并验证结果是否符合预期。测试并不关心这些对象如何在内部实现结果,只关注结果符合预期。

一般来说,单元测试遵循三个步骤:

  1. 安排
  2. 断言
  3. 那是......

    首先,您安排测试对象。这可能涉及将一些静态数据重置为已知状态,实例化对象(或从工厂抓取它等),设置一些属性等。基本上,您正在创建一个运行测试的已知状态。 / p>

    其次,你采取行动。您执行一些应该以某种方式更改系统状态的操作。通常这只是在对象上调用一个方法(或者在某些情况下可能将对象传递给其他地方的方法)。这是你正在测试的。更改系统状态的代码会将其从一个已知状态更改为另一个预期结果状态。

    第三,你断言测试的结果。由于您在第一步中创建了一个已知状态,因此在第二步中更改了状态,现在您在第三步中观察到了结果状态。

答案 1 :(得分:0)

您可以通过多种方式使用NUnit。这取决于您的代码以及您的测试的全部内容。在您的情况下,比较总计,您将使用AreEqual方法。另一个常见的例子是,如果您想查看代码是否生成异常 - 可能是检查库更新等。类似于以下内容可能有用:

        [TestCase]
        public void TestCase()
        {
            try
            {
                // Write you code here that might generate an exception

                Assert.AreEqual(true, true);
            }
            catch (Exception e)
            {
                Assert.Fail(e.Message, e.GetType().Name);
            }
        }

正如您所看到的,如果执行成功,我使用AreEqual,并将true与true进行比较,以便它可以正常执行。但是,如果代码生成异常,我将发回错误消息。