【问题标题】:Resetting a private static int from a junit test class从junit测试类重置私有静态int
【发布时间】:2016-11-09 19:59:59
【问题描述】:

我正在尝试为一个名为 Student 的类编写一些 junit 测试。基本上,每个学生都有一个 studentNum,它被设置为一个迭代器,它是一个私有静态整数。每次创建新学生时,studentNum 都会增加。

我对一个函数进行了几个测试,该函数从传入的学生数组列表中获取学生人数为 1 的学生。但是,每次我在新测试中创建一个新的学生数组列表时,studentNum 都会从上一个测试的 studentNum 停止的地方开始。所以第一个测试会让学生的 studentNums 从 0 到 5,第二个测试会让学生的 studentNums 从 6 到 11。

我想知道是否有办法从我的测试类中重置私有静态 studentNum 整数,以便我可以让它在每个测试中从 0 开始?任何帮助将不胜感激。

【问题讨论】:

  • 可能你想要一个在每次测试之前调用的@Before 方法。
  • 你的代码在哪里?
  • 只需在每个测试方法之前创建一个新的Student 夹具。
  • 正确答案几乎可以肯定是“不要为此使用静态变量,而是使用外部计数器”。
  • 创建一个新的 StudentList (或 StudentFactory 或任何您命名的状态)对象,使计数器成为非静态字段,如果您将其放入 before 方法中,您将始终拥有干净的测试上下文并且没有依赖项或缺少清理工作。

标签: java unit-testing junit


【解决方案1】:

您发现这很难测试这一事实是一个警告信号,您可能需要重新考虑您的设计。问问自己这个问题:Student 类为什么要负责生成唯一的 id?

如果您将 id 生成逻辑(即使它像增加单个计数器一样简单)分离到一个单独的类中,那么您突然可以在测试 Student 时模拟该类并让它返回任何您在测试中想要的 id。

【讨论】:

  • 或者您只需使用在测试中选择的 ID 实例化 Student
  • @chrylis 是的,如果需要的话,有很多方法可以将 id 输入到学生对象中。但重要的是单一职责原则:Student 类不应负责 id 生成(或保留实例列表或类似的东西)。
【解决方案2】:

每个学生都有一个studentNum,它是一个私有的static int

这种说法毫无意义。如果 Student 对象的每个实例都有自己的 id,则根据定义,id 字段应该是静态的。

【讨论】:

  • 对不起,你是对的。在 Student 类中实际上有一个私有静态迭代器,studentNum 在构造函数中被设置为。
【解决方案3】:

查看@Before/@After 注释。像这样注释的方法在每个测试用例运行之前/之后被调用。您可以在那里重置您的数据。

@Before
public void setup(){

}

【讨论】:

    【解决方案4】:

    想想静态 decalration 是什么意思... 出于实际目的,如果 studentNum 包含 Student 唯一编号,则它不能是静态的。使用静态时,您的所有 Student 对象都将具有最新的 studentNum。

    但如果这是一个要求(无法想象是什么......),那么对于具有多个@Test 方法(并且仅具有)R O M A N I A 的junit 是正确的。这样做:

    @Before
    public void setUp() throws Exception {
        Student.studentNum =0;
    }
    

    它会在执行每个@Test 方法调用之前重置静态studentNum。

    【讨论】:

      【解决方案5】:

      您可以使用 @Before@After(或两者)使用 Java 的反射 API 将私有静态字段重置为您希望的任何值(例如 0)。

      这样做的方法是:

      @Before
      public void setup() throws Exception {
          Field studentNum = Student.class.getDeclaredField("studentNum");
          studentNum.setAccessible(true); //to overcome the visibility issue
          studentNum.setInt(null, 0); //null since it's static
      }
      

      【讨论】:

      • 虽然这种方法可行,但您不应该使用它。访问对象的私有成员(即使是为了测试)违反了 OOP 中最重要的原则:信息隐藏!另外:如果你开始测试实现细节(而不是 ob 行为),如果你想重构你的代码,你的测试会咬你。
      • 我同意你的观点,在测试中必须使用反射很可能是code smell。但是,您的建议是如何更好地构造代码,以保持它的良好封装和单一职责,使其在过程中可测试,而 OP 希望保持代码原样,但要克服可测试性问题,这是一个非常有效的场景,尤其是在旧代码/遗留代码的情况下,重构不是一个简单的过程,而且很可能不值得(业务方面)。
      • “虽然 OP 想要保持代码原样,但要克服可测试性问题” 什么时候开始更好地编码?对我来说是现在。为 OP 提供反射解决方案使她对破碎的编码/测试风格感到厌烦。 是否希望同事做 OP 试图做的事情? 没有!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-05
      • 1970-01-01
      • 1970-01-01
      • 2012-03-30
      • 2015-04-17
      • 1970-01-01
      相关资源
      最近更新 更多