1

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

我给出了一个测试用例的例子,请检查。

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

那是对的吗 ?

[测试方法]

    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();             
        }
4

2 回答 2

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. 断言

那是...

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

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

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

于 2013-06-10T13:15:43.657 回答
0

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

        [测试用例]
        公共无效测试用例()
        {
            尝试
            {
                // 在此处编写可能会产生异常的代码

                断言.AreEqual(true, true);
            }
            捕获(异常 e)
            {
                Assert.Fail(e.Message, e.GetType().Name);
            }
        }

如您所见,我使用 AreEqual 是否成功执行,并将 true 与 true 进行比较,因此它会执行得很好。但是,如果代码生成异常,我会发回错误消息。

于 2013-06-10T13:14:24.277 回答