【问题标题】:Testing an abstract class with Mockito does not give the expected result使用 Mockito 测试抽象类并没有给出预期的结果
【发布时间】:2020-03-02 08:06:04
【问题描述】:

我有一个类似于下面的类结构

 public abstract class AbstractStep {
     private final Range RANGE;

     AbstractStep(AbstractStepBuilder builder) {
          RANGE = builder.range;   
     }


      public abstract static class AbstractStepBuilder {
           Range range;

           public AbstractStepBuilder setRange(int start, end end) {
                this.range = new Range(start, end);
                return self();
           }

           abstract AbstractStepBuilder self();
      }

      public static class Range() {
           private final int START;
           private final int END;

           private Range(int start, int end) {
                if(start < 0 || end < 0 || start >= end)
                      throw new IllegalArgumentException();
                START = start;
                END = end;
           }
      }
 }

我想在AbstractStepBuilder 中测试setRange(int, int),看看是否抛出了IllegalArgumentException。我使用 TestNG 和 Mockito,并在 this 的帮助下尝试了以下使用。

 final class RangeTest {
      AbstractStepBuilder builder;

      @BeforeSuite 
      void setup() {
           builder = Mockito.mock(AbstractStepBuilder.class);
           Mockito.when(builder.self()).thenReturn(null);
       }

     @Test(expectedExceptions = IllegalArgumentException.class)
     final void testCreatingRangeWithNegativeStart() {
          builder.setRange(-1, 2);
     }
}

此测试失败。我还尝试将Mockito.mock(AbstractStepBuilder.class) 替换为Mockito.mock(AbstractStepBuilder.class, Mockito.CALLS_REAL_METHODS),如this 问题的最佳答案。

请注意,如果我将 CodeRange 作为自己的外部类,则此测试通过,所以我不相信它可能是测试本身。

为什么这个测试会失败,是否可以在不使用测试中的具体类的情况下修复它?

【问题讨论】:

  • 你根本不调用 AbstractStepBuilder#setRange
  • 你得到什么错误?
  • @kofemann 已修复,由于从更复杂的项目中复制,因此抱歉
  • @ThomasMartin RangeTest 中的测试失败
  • “我们可以在不使用测试中的具体类的情况下修复它吗?”具体来说不是,因为您不能在具体类上调用实例方法。它必须是具体的。在测试范围内创建一个最小的子类看起来是正确的方法。

标签: java mockito testng abstract-class


【解决方案1】:

你在模拟上调用一个方法,在你告诉它之前永远不会抛出异常。你永远不会模拟你想测试的课程。

如果您想测试实际的类,您需要创建 step builder 的子类,创建一个实例并对其进行测试。

我认为您还可以创建一个间谍(Mockito.spy(AbstractStepBuilder.class))以避免仅为测试创建子类。

【讨论】:

  • @davidxxx 是的,但我懒得在文档中找到建议反对它的部分:P 此外,专门为测试创建子类对我来说也有代码味道。所以我想这是两害相权取其轻的情况。
  • 为测试创建一个子类也不一定是今天最好的事情,我同意 :) 也许它们之间的路径是可能的 :)
  • @davidxxx 也许定义一个子类,然后创建一个间谍...... ;)
  • 这不是两个世界中最糟糕的吗?不,我认为您的第一个想法很好。通常我不会尝试测试抽象类,因为那是抽象的。如果我真的需要这样做,因为例如这是我向其他客户公开的一个类,那么在测试范围内创建一个子类并不是什么难闻的气味。无论你对第一点投我的票:)
  • @davidxxx 是的,那是个玩笑。
猜你喜欢
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 2020-05-29
  • 1970-01-01
  • 2019-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多