为了账号安全,请及时绑定邮箱和手机立即绑定

在单元测试中避免外部输入

在单元测试中避免外部输入

慕无忌1623718 2023-02-23 18:09:38
我想对 a 进行单元测试class A。这个类与其他类级联,所以class A创建了一个实例class B和class B的class C。像那样:public class A {    public B b;    public A() {        this.b = new B();    }} public class B {    public C c;    public B() {        this.c = new C();    }} 如果现在类 C 在其构造函数中读取任何外部输入,如文件或属性,我如何避免这种情况?我看不出你会如何模拟它,但是在测试时是否也有可能将外部因素排除在其他类之外?
查看完整描述

4 回答

?
心有法竹

TA贡献1866条经验 获得超5个赞

您在这里遇到的问题是您的类与其他类的特定实现紧密耦合,因此您的“单元”被迫一起测试所有这些类的行为。


避免这种情况的典型方法是使用依赖注入,使您的类与接口而不是特定类耦合。然后您可以模拟注入的接口以对单个类的行为进行单元测试。


public class AImpl {

    public B b;

    public AImpl(B b) {

        this.b = b;

    }

}


public interface B {

    // methods

}


public class BImpl implements B {

    public C c;

    public BImpl (C c) {

        this.c = c;

    }

}

当您创建AImpl生产代码时,您现在必须为其提供特定的C实现。您可以这样做new AImpl(new BImpl(new CImpl)),也可以使用像 Spring 这样的依赖注入框架来为您计算出所有这些细节。


B当您进行单元测试时,您可以创建一个模拟或存根以具有您希望为该特定测试展示的行为,并将该存根传递给构造函数: new AImpl(myMockedB)。


查看完整回答
反对 回复 2023-02-23
?
慕丝7291255

TA贡献1859条经验 获得超6个赞

B您不应该在类中创建实例A- 相反,您应该B在创建时提供实例A- 它称为Inversion of Control。流行的方法是使用依赖注入,例如使用 Spring 框架。

然后一切都变得简单 - 当您的类需要读取带有类的文件时FileReader,为了测试您可以创建一个“假”实现,例如当您调用时FileReader.readFile(),您的假实现将简单地返回硬编码字符串或流,具体取决于您想要什么。

这个概念真的很大,想象一下当你FileReader实际上是一个DatabaseReaderor ExternalServiceCaller。不是在单元测试中测试真实的数据库(祝你好运),而是创建一个FakeDatabaseReader在常规 Java 上运行的数据库HashMap,一切都很容易测试。

或者当您的代码处理时间/日期时,想象一个功能只在29th February- 您可以等待 4 年来测试它,或者为Clock您的测试提供一个设置为特定日期的对象。该类Clock具有提供各种替代时钟的静态方法,以提供固定时刻、调整到未来或过去的时刻,或具有改变节奏的时钟


查看完整回答
反对 回复 2023-02-23
?
潇湘沐

TA贡献1816条经验 获得超6个赞

首先,由于您不能注入 B 类,因此所有此类都不是为了进行温和测试而设计的,请注意,由于您将任何新内容添加到类中,这与对实例进行硬编码非常相似。


适当的方式应该是


  public class A {

    public B b;

    public A(B b) {

        this.b = b;

    }

}

请注意,您可以通过这种方式实例化类


A a = new A(b); 

这样,b 可以是模拟或虚拟或存根或任何用于测试目的的对象。如果您面临遗留代码,您应该重构它以使其能够被测试。如果这是您的设计,您应该尽快重构以使其可测试。


控制反转和依赖注入应该有助于归档你想做的事情。


查看完整回答
反对 回复 2023-02-23
?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

不是我知道的,你会处理这些外部因素,或者在 A、B 或 C 类本身的开发过程中确保在测试过程中不会出现此类问题。

但是,如果您无法控制 A、B 或 C 类源,那么我认为您被卡住了!


查看完整回答
反对 回复 2023-02-23
  • 4 回答
  • 0 关注
  • 84 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信