如何组织或分类单元测试 DAO 搜索方法

Posted

技术标签:

【中文标题】如何组织或分类单元测试 DAO 搜索方法【英文标题】:How to organise or categorise unit testing DAO search methods 【发布时间】:2011-12-31 11:15:18 【问题描述】:

首先,请原谅我在可能指集成测试时使用了“单元”一词。但是,在这种情况下,我将 DAO 方法的测试视为一个单元,而不是试图模拟下划线数据库。

我一直在尝试测试搜索特定实体的特定 DAO 方法 -

public Factor GetMatchingFactor(int aircraftStoresConfigurationId, int stationId, DateTime timeStamp)

    // code etc....

不,通常情况下,我会尝试进行多个单元测试,可能每个参数都进行一些测试,以确保每个参数都得到适当的处理。当方法本身处理参数时,我通常对此感到满意,更糟糕的是调用我可以使用模拟/存根测试的依赖项。然而,在这个特定的方法中,方法的结果不是一个纯函数或一个参数,而是参数和测试数据的函数。

因此,我很难定义类似的测试

public void TestThatAircraftStoresConfigurationIdParameterIsApplied
public void TestThatStationIdParameterIsApplied
public void TestThatTimeStampParameterIsApplied

由于他们的名字不正确,每个人不只是测试一件事。

这也意味着我很难遵守每次测试只有一个 Assert 的规则。

因此,我使用以下代码测试了此方法,覆盖率相同,并且可能更有意义。

    [Test]
    public void TestReturnsCorrectResult()
    
        Assert.That(_sut.GetMatchingFactor(10001, Station.Station9Id,  new DateTime(2011, 11, 16, 10, 00, 00)).Id, Is.EqualTo(1), "Test 1");
        Assert.That(_sut.GetMatchingFactor(10001, Station.Station9Id,  new DateTime(2011, 11, 16, 11, 00, 00)).Id, Is.EqualTo(1), "Test 2");
        Assert.That(_sut.GetMatchingFactor(10001, Station.Station9Id,  new DateTime(2011, 11, 16, 19, 00, 00)).Id, Is.EqualTo(1), "Test 3");
        Assert.That(_sut.GetMatchingFactor(10001, Station.Station9Id,  new DateTime(2011, 11, 16, 19, 00, 01)).Id, Is.EqualTo(2), "Test 4");
        Assert.That(_sut.GetMatchingFactor(10001, Station.Station9Id,  new DateTime(2011, 11, 16, 19, 00, 02)).Id, Is.EqualTo(2), "Test 5");
        Assert.That(_sut.GetMatchingFactor(10001, Station.Station9Id,  new DateTime(2011, 11, 16, 14, 00, 00)).Id, Is.EqualTo(1), "Test 6");
        Assert.That(_sut.GetMatchingFactor(10001, Station.Station10Id, new DateTime(2011, 11, 16, 14, 00, 00)).Id, Is.EqualTo(1), "Test 7");
        Assert.That(_sut.GetMatchingFactor(10002, Station.Station11Id, new DateTime(2011, 11, 16, 14, 00, 00)).Id, Is.EqualTo(3), "Test 8");
        Assert.That(_sut.GetMatchingFactor(10002, Station.Station12Id, new DateTime(2011, 11, 16, 14, 00, 00)).Id, Is.EqualTo(3), "Test 9");
    

我对多个断言不太满意,但这似乎是构建这些测试的唯一合乎逻辑的方法。谁能提出更好的选择?

【问题讨论】:

【参考方案1】:

这似乎非常适合 NUnit 2.5 中的 TestCases。你可以重写你的代码如下:

[TestCase(10001, Station.Station9Id,   2011, 11, 16, 10, 00, 00,  1)]
[TestCase(10001, Station.Station9Id,   2011, 11, 16, 11, 00, 00,  1)]
[TestCase(10001, Station.Station9Id,   2011, 11, 16, 19, 00, 00,  1)]
[TestCase(10001, Station.Station9Id,   2011, 11, 16, 19, 00, 01,  2)]
[TestCase(10001, Station.Station9Id,   2011, 11, 16, 19, 00, 02,  2)]
[TestCase(10001, Station.Station9Id,   2011, 11, 16, 14, 00, 00,  1)]
[TestCase(10001, Station.Station10Id,  2011, 11, 16, 14, 00, 00,  1)]
[TestCase(10002, Station.Station11Id,  2011, 11, 16, 14, 00, 00,  3)]
[TestCase(10002, Station.Station12Id,  2011, 11, 16, 14, 00, 00,  3)]
public void TestReturnsCorrectResult(int configId, int stationId, int yy, int mm, int dd, int h, int m, int s, int expectedResult)

    Assert.That(_sut.GetMatchingFactor(configId, stationId, new DateTime(yy,mm,dd,h,m,s)).Id, Is.EqualTo(expectedResult));

现在只有一个断言,但要测试多个事物。对于像您描述的那样的集成测试来说,这真是太好了。

请注意,您只能通过 TestCase 属性传递常量,因此您将无法新建 DateTime 对象。相反,您必须将年、月、日等作为参数传递给方法,然后自己实例化 DateTime。

您也可以考虑使用一些 T4 脚本从一些其他数据(例如 CSV 文件)生成您的 TestCase 属性。我过去曾使用过这种方法并取得了相当大的成功,它允许最终用户在 Excel 中创建测试用例,然后将它们传递给您。

【讨论】:

以上是关于如何组织或分类单元测试 DAO 搜索方法的主要内容,如果未能解决你的问题,请参考以下文章

Springboot单元测试调用Service或Dao方法出现空指针异常

如何使用 Spring Security 对 Spring 4 DAO 方法进行单元测试?

在 DAO 单元测试期间恢复数据的策略是啥?

单元测试 DAO

如何在 Java 中对 DAO 应用单元测试

没有内存数据库的单元测试 dao 层