代码之家  ›  专栏  ›  技术社区  ›  Nirman

当数据库架构和实体发生更改,但单元测试未更改时,单元测试将失败

  •  0
  • Nirman  · 技术社区  · 5 年前

    以下是我的应用程序中的确切场景:

    • 与SQL数据库对话的框架。
    • 单元测试针对所有方法编写,并基于方法签名、输入要求和返回值覆盖所有可能的排列和组合。
    • 单元测试运行良好,并且在应该失败的时候失败(例如,一些验证被更改或预期返回值发生更改,但是单元测试不会反映相同的情况)。
    • 有些情况下,开发人员在SQL模式中执行更改,并在C代码中更新实体。在这种情况下,单元测试正在通过,这是绝对正确的,因为它的底层逻辑被更改了,而不是输入、验证或返回值。

    有人能建议一下如何达到同样的效果吗?

    如果能在这方面提供任何帮助,我们将不胜感激。

    谢谢

    0 回复  |  直到 5 年前
        1
  •  1
  •   Flater    5 年前

    我把最后一段移到前面是因为它看起来像是你的X XY problem . 我建议阅读所有其他段落,因为你似乎误解了什么是单元测试,以及它的作用。

    单元测试不测试多个代码库!

    因此,如果一个项目的开发人员更改了数据库模式,我们要提醒他们,这种模式更改也应该反映在其他项目中。

    不应将单元测试用作同步两个完全不相关的代码基的方法。

    单一的 两个应用程序都依赖的源。

    例如,您可以在Nuget服务器上托管“共享数据”项目,并让两个应用程序都引用自托管的Nuget包。正确配置后,无论何时构建应用程序,它都将获取“共享数据”项目的最新版本,从而确保两个应用程序始终使用最新版本的数据库架构。

    第二种方法(如果您不想创建共享依赖项)是让您的subversion系统观察某些文件(例如实体类文件夹),并在这些文件中发生任何更改时向您发出警报。当您收到警报时,您将注意检查此更改是否会影响其他应用程序的代码库。
    如果我没听错的话,你真的只是想引起警觉,对吧?

    但绝对不应该通过手动编写脚本/伪造单元测试失败来完成。


    当数据库架构和实体发生变化时,我希望一些单元测试失败

    单元测试 事物(因此称为“单位”)。似乎您正在编写测试两个方面的测试:业务逻辑和数据库。这是一个集成测试。根据经验法则:

    • 集成测试测试

    不测试外部依赖项

    如果要专门为EF编写一个单元测试(您不应该这样做,但稍后会详细介绍),那么您实际上不会在测试中涉及实际的数据库。充其量,您将断言由EF生成的SQL,而不在数据库上运行该查询。

    重复我的观点,单元测试 不同的东西。

    当使用外部组件(例如数据库服务器)时,您再次深入到集成测试领域。


    只测试你自己的代码

    不要 想知道它的内部工作原理。

    考虑这个测试:

    public void TestForAddition()
    {
        var expectedValue = 2;
        var testValue = 1 + 1;
    
        Assert.AreEqual(testValue,expectedValue);
    }
    

    + 代码,因此您不应该测试它。这个想法和EF的论点是一样的:这不是你的代码,也不是由你来测试。你必须信任你所使用的依赖关系。

    但是,如果您的 + 接线员,你应该测试一下 代码)

    public static Person operator+ (Person a, Person b) 
    {
       return new Person() { Name = a.Name + " " + b.Name };
    }
    
    public void TestForPersonAddition()
    {
        var expectedValue = "Billie Jean";
    
        var billie = new Person() { Name = "Billie" };
        var jean = new Person() { Name = "Jean" };
    
        Assert.AreEqual(billie + jean,expectedValue);
    }
    

    对于以EF为中心的例子来说,这意味着 . 你应该只对你的代码进行单元测试,而不是EF的。
    但是,您可以为此编写集成测试。这可以实现您想要的:对现有数据库运行集成测试。如果集成测试通过,您将知道新的代码库与现有数据库兼容。如果他们没有,那么你就知道发生了一个需要开发人员注意的问题。


    但是,我希望在数据库架构和实体发生更改时,某些单元测试失败,但单元测试没有更改。也就是说, 我希望开发人员修复单元测试

    所以你想让你的开发人员修复那些一开始就没有被破坏的单元测试?

    制作 它们失败了,所以你的开发人员就被迫“修复”单元测试(一开始就没有被破坏)。

    .

    你在滥用单元测试。问题并不是试图找出如何强制单元测试失败;问题是您希望单元测试的结果告诉您什么。
    单元测试不应用于测试内部系统是否已更改。 单元测试测试应用程序是否仍然以相同的方式运行

    如果我从头开始重写你的代码库,然后在我的新代码库上运行相同的(未触及的)单元测试,并且所有单元测试都通过了,那就意味着 我的代码和你的一样 我们的代码库在功能上是相互等价的(至少在编写测试的行为方面是这样的)