具有深度嵌套依赖项的单元测试和依赖项注入

2024-03-11

假设遗留类和方法结构如下

public class Foo
{
    public void Frob(int a, int b)
    {
        if (a == 1)
        {
            if (b == 1)
            {
                // does something
            }
            else
            {
                if (b == 2)
                {
                    Bar bar = new Bar();
                    bar.Blah(a, b);
                }
            }
        }
        else
        {
            // does something
        }
    }
}

public class Bar
{
    public void Blah(int a, int b)
    {
        if (a == 0)
        {
            // does something
        }
        else
        {
            if (b == 0)
            {
                // does something
            }
            else
            {
                Baz baz = new Baz();
                baz.Save(a, b);
            }
        }
    }
}

public class Baz
{
    public void Save(int a, int b)
    {
        // saves data to file, database, whatever
    }
}

然后假设管理层发布了一项模糊的任务,要求对我们所做的每一项新事物(无论是添加的功能、修改的需求还是错误修复)执行单元测试。

我可能比较坚持字面解释,但我认为“单元测试”这个词是有一定含义的。例如,这并不意味着给定输入 1 和 2,单元测试Foo.Frob仅当 1 和 2 保存到数据库时才会成功。根据我读到的内容,我相信它最终意味着基于 1 和 2 的输入,Frob调用Bar.Blah。无论是否Bar.Blah做了应该做的事并不是我最关心的事情。如果我关心测试整个过程,我相信还有另一个术语,对吗?功能测试?场景测试?任何。如果我太严格了,请纠正我!

目前坚持我的严格解释,让我们假设我想尝试利用依赖注入,其中一个好处是我可以模拟我的类,这样我就可以,例如,not将我的测试数据保存到数据库或文件或任何情况下。在这种情况下,Foo.Frob needs IBar, IBar needs IBaz, IBaz可能需要一个数据库。这些依赖项要注入到哪里?进入Foo?或者确实Foo只是需要IBar, 进而Foo负责创建一个实例IBaz?

当您进入这样的嵌套结构时,您很快就会发现可能需要多个依赖项。执行此类注射的首选或可接受的方法是什么?


让我们从你的最后一个问题开始。依赖项在哪里注入:一种常见的方法是使用构造函数注入(如福勒描述的 http://martinfowler.com/articles/injection.html). So Foo被注入IBar在构造函数中。具体实施IBar, Bar依次有一个IBaz注入到它的构造函数中。最后是IBaz执行 (Baz)有一个IDatabase(或其他)注入。如果您使用 DI 框架,例如城堡计划 http://www.castleproject.org/,您只需要求 DI 容器解析一个实例Foo为你。然后它将使用您配置的任何内容来确定哪个实现IBar您正在使用。如果它确定您的实施IBar is Bar然后它将确定哪个实施IBaz你正在使用等等

这种方法为您提供的是,您可以单独测试每个具体实现,并且只需检查它是否正确调用(模拟的)抽象。

对于您对过于僵化等问题的担忧,我唯一能说的是,在我看来,您选择了正确的道路。也就是说,当实施所有这些测试的实际成本对管理层来说显而易见时,他们可能会感到惊讶。

希望这可以帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有深度嵌套依赖项的单元测试和依赖项注入 的相关文章

随机推荐

  • 参数类型“Stream”无法分配给参数类型“Stream?”

    我想使用 Streams 使用 firebase 身份验证 但是我在网上收到上述错误stream FirebaseAuth instance authStateChanges 我努力了onAuthStateChange 那也行不通 clas
  • Abaqus Surface getSequenceFromMask

    我正在 Abaqus 中编写脚本 我用切圆 像奶酪 压碎圆形和正方形 我需要在部件之间放置接触 所以我需要 Surface 宏管理器生成 s1 a instances kolo 1 edges side1Edges1 s1 getSeque
  • 在 Codeigniter 中加密时避免使用特定字符?

    我需要通过 URL 传递一些加密值 有什么办法可以避免加密后得到的值中出现一些字符 例如斜杠 因为在codeigniter中 斜杠等字符用于分隔URL中的参数 请注意 我不希望任何建议不要在 URL 中传递加密字符串 使用PHPurlenc
  • 用于索引和搜索的 Lucene 分析器

    我有一个正在使用 Lucene 建立索引的字段 如下所示 Field name hungerState index Index TOKENIZED store Store YES public HungerState getHungerSt
  • 如何更新角度材质

    将项目中的角度材料更新到最新版本的最佳方法是什么 email protected cdn cgi l email protection I tried npm install save angular material angular cd
  • 我应该使用字符串表来提高数据库效率吗?

    假设您有一个包含单个表的数据库 例如 Name FavoriteFood Alice Pizza Mark Sushi Jack Pizza 如果有一个名为 St
  • 在 git bash 中找不到 sudo/apt-get 命令

    我在我的机器上使用 Windows 10 当前安装了 git bash 我想为我的应用程序安装 Node 和 npm 当我尝试时 apt get安装nodejs 找不到 apt get 命令 我尝试谷歌并得到 须藤安装nodejs 未找到
  • 页面重新加载时 Jquery 显示/隐藏重置

    我是 jquery 的新手 但我正在尝试使用它来创建多步骤选项卡式表单 在其中一页 我有单选按钮 将根据所选的选择显示多个字段 我发现的问题是 如果用户在选择单选按钮后刷新页面 页面将重新加载并隐藏所有 div 但它会记住所选的单选按钮选项
  • 将项目推送到 STL 容器后出现段错误

    typedef struct temp int a b char c temp c char malloc 10 temp free c temp int main temp a list
  • 插入行以用标题分隔数据组

    有人可以帮我写这个脚本吗 就目前情况而言 一旦值 文本发生更改并插入新行 当前的宏就会分离数据 但我只是无法弄清楚如何在插入行后包含标题 Sub Insert Row Dim ws As Worksheet Dim lr As Long D
  • 无法使用 VS 代码从 Node js 中的控制台读取

    我正在 VS code 中使用 Node js 的核心模块 但无法让它与 readline 模块一起工作 我在 js 文件中有以下代码 const readline require readline const rl readline cr
  • 使用布尔索引数组过滤列表

    如何在不使用 numpy 的情况下使用布尔索引数组来过滤列表 例如 gt gt gt l a b c gt gt gt b True False False gt gt gt l b 结果应该是 a 我知道 numpy 支持它 但想知道如何
  • ruby 打印 2 个字符串之间选定的文本行

    我试图在 ruby 中的两个字符串之间获取一组文本 但我似乎无法获得正确的方法或使用正确的正则表达式 text h1 all kinds of html h1 p blah blah p p i ve been working on thi
  • MVC 软件架构中验证逻辑的放置位置

    我其实已经开始学习mvc架构了 我很困惑是否将用户名注册验证逻辑放在模型中或控制器中 我有某种状态消息 可以告诉用户要注册的新用户名是否可用 我开始感到困惑 因为大多数消息来源说它应该在模型中 因为它涉及在将用户名数据放入数据库之前进行验证
  • IPC 的共享内存和线程的共享内存有什么区别?

    让我们使用 POSIX 共享内存 例如 shmget 协调进程间通信的常见调用 调用 shmget 并协调共享内存段上的通信与 Linux 在单个进程中实现共享内存和线程之间的同步有何不同 其中之一更轻吗 SHM适用于多进程中的IPC 在现
  • postgresql 中的 regexp \Q...\E 等价于什么?

    我有以下查询 SELECT field FROM myTable WHERE field Qprefix E 它不会找到类似的值prefix foo 我该如何更换 Q E 这种形式的正则表达式带有 Q E仅支持不带引号的子字符串PCRE h
  • 从 shell 脚本中提取 YAML 中的变量

    我有一个由以下内容组成的 YAML 文件 acceleration matrix 1ere row x 20 0 0 15 15 2eme row y 0 15 0 0 0 3eme row z 0 0 30 15 15 4eme row
  • NLTK 中 Text.similar() 和 ContextIndex.similar_words() 生成的单词按频率排序?

    我使用这两个函数来查找相似的单词 它们返回不同的列表 我想知道这些函数是否按最频繁关联到最不频繁关联排序 ContextIndex similar words word http nltk org modules nltk text htm
  • 使用剪辑的条件或选择性规则

    我希望你过得很好 我是 CLIPS 的初学者 我有一个包含多个节点 起始节点 输入 和结束节点 输出 的图表 我想在输入数量等于输出的情况下创建一个规则 该规则必须帮助我在几个节点之间进行选择组合 起始节点和结束节点 每个组合的最短路径 如
  • 具有深度嵌套依赖项的单元测试和依赖项注入

    假设遗留类和方法结构如下 public class Foo public void Frob int a int b if a 1 if b 1 does something else if b 2 Bar bar new Bar bar