【问题标题】:pit mutation - if ( x !=null ) return null else throw new RuntimeException坑突变 - if ( x !=null ) return null else throw new RuntimeException
【发布时间】:2019-08-01 22:06:30
【问题描述】:

我有一个返回自定义对象的方法

public MyObject getTheObject(){
  ...
  return muObject;
}

它的单元测试检查getTheObject()方法返回的对象不为空

@Test
public void testGetTheObject(){
  ...
  assertNotNull(actualObject);
}

测试通过。

当运行突变测试with Pitest 时,它会显示一个SURVIVED 突变,它会这样说:

mutated returned of Object for value for ..../getTheObject to ( if ( x!= null ) null else throw new RuntimeException )

问题是我们的单元测试应该是什么样子才能摆脱这个问题,以及KILL那个突变

【问题讨论】:

  • 我不知道SURVIVEDKILL 在这种情况下是什么意思。请向我们展示产生您所询问的输出的代码。我们无法仅从一些随机错误消息中猜测发生了什么。
  • 在这种情况下x 是什么?
  • 坑文档中所说的 x 是我在 getTheObject() 方法中返回的对象。 SURVIVED 表示如果pit 改变(更改)我的代码中的某些内容,我的单元测试仍然通过,KILL 表示pit 突变无法让我的单元测试通过。
  • 要回答你的问题,我们需要知道哪个突变体没有杀死它的突变体之一。在这样的行之后查看 maven 日志:> org.pitest.mutationtest.engine.gregor.mutators.ReturnValsMutator >> Generated 2 Killed 1 (50%) > KILLED 1 SURVIVED 0 TIMED_OUT 0 NON_VIABLE 0 > MEMORY_ERROR 0 NOT_STARTED 0 STARTED 0 RUN_ERROR 0 > NO_COVERAGE 1
  • 你可以提供整个例子吗?

标签: java unit-testing mutation-testing pitest


【解决方案1】:

它是 PIT 的“返回值修改器”(当返回类型为 Object 时),它将用 null 替换非 null 返回值,如果未突变的方法返回 null,则抛出 java.lang.RuntimeException。

即变异代码:

public MyObject getTheObject(){
  ...
  return null;
}

上面的 mutator 预计您的 Junit 应该失败,但由于运行时异常原因。 assertNotNull(getTheObject()) 只是检查返回对象是否为空,仅通过检查对象值是无法获得运行时异常的。

要杀死这个 mutator,你可以调用该对象的任何方法(例如 getter())。 现在,如果您在空对象上调用任何方法(由上述静音代码返回),那么您将获得空指针异常(即Runtime exception),并且您的 Junit 将因静音代码而失败。

回答:

assertThat(getTheObject().getterOfAnyField(),is(expectedValue));

或者

assertNotNull(getTheObject().getterOfAnyField());

【讨论】:

  • 你能试着更好地解释一下答案吗?我看不到assertThat(mutationTestService.getClassAObj(10).getA(),is(10));getTheObject(){return null;} 之间的联系。我也不明白为什么assertNotNull 不足以杀死突变体。由于 mutator 返回 nullassertNotNull 应该无法通过单元测试。我错过了什么?谢谢!
  • @MaxVollmer 我稍微改进了我的答案。我希望它对你有帮助。Return value mutator 的坑期待测试用例应该失败,但由于运行时异常原因。谢谢
  • 这里是pitest的作者。尽管通常您可能希望测试不仅仅断言返回值不为空,但简单的 assertNotNull 应该足以杀死这种突变,因此这个答案是不正确的。
【解决方案2】:

我无法重现此问题(即相同的突变被正确杀死)。我认为您的问题没有包含足够的上下文(其他“pitest 不起作用”所以问题似乎围绕着 Spring 和/或 Mockito 的使用,这两者都还修改了字节码/制作了额外的类)

https://stackoverflow.com/help/minimal-reproducible-example

  • Gradle 5.2.1
  • JUnit 5
  • Pitest 1.4.5
    public class SO55104467 {
      public static class MyObject {}
      private final MyObject muObject = new MyObject();
      public MyObject getTheObject(){
        return muObject;
      }
    }

    class SO55104467Test {
      private SO55104467 sut = new SO55104467();
      @Test
      public void testGetTheObject(){
        SO55104467.MyObject actualObject = sut.getTheObject();
        assertNotNull(actualObject);
      }
    }

【讨论】:

  • 谢谢drekbour,我不记得我在哪里结束了,但谢谢你的帮助。
猜你喜欢
  • 2015-10-28
  • 1970-01-01
  • 2015-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-20
相关资源
最近更新 更多