5

I have a method that returns a custom object

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

its unit test checks that the object returned by getTheObject() method is not null

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

and test passes.

When running mutation test with Pitest it shows one SURVIVED mutation which says something like this:

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

The question is what should our unit test look like to get rid of this issue, and KILL that mutation

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Toseef Zafar
  • 1,601
  • 4
  • 28
  • 46
  • 1
    I have no idea what `SURVIVED` and `KILL` mean in this context. Please show us the code that produces the output that you're asking about. There's no way we can guess what's going on just from some random error message. – markspace Mar 11 '19 at 14:50
  • What is `x` in this context? – khelwood Mar 11 '19 at 14:51
  • what pit documentation says x is the object that I am returning in the getTheObject() method. SURVIVED means if pit mutates (changes) something in my code, my unit test still passes, KILL means the pit mutations can not get my unit test pass. – Toseef Zafar Mar 11 '19 at 14:53
  • Ton answer your question, we need to know which mutator did not kill one of its mutations. Look in the maven log after lines like this: `> 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 ` – Benoit Mar 11 '19 at 16:29
  • I think its RETURN_VALS_MUTATOR, I am using IntellijIdea and running it through a plugin which generates HTML reports. – Toseef Zafar Mar 11 '19 at 16:32
  • 1
    Do you could make the whole example available? – PowerStat Jun 07 '19 at 14:26
  • Toseef: Could you please respond to the comments for clarification and try to improve this question - or, if you found a solution, post it as an answer yourself? I have added a bounty to your question, because another user has posted a very similar question which got closed as duplicate of your question, but it seems that your question actually lacks information to be answerable in a satisfying way. – Max Vollmer Oct 28 '19 at 12:19
  • Max: apologies, I put the question long time ago, and have forgotten what I ended up with to KILL that mutation. – Toseef Zafar Nov 02 '19 at 13:44

2 Answers2

5

I cannot reproduce this problem (i.e. same mutation is correctly KILLED). I don't think your question includes enough context (other "pitest didn't work" SO questions seem to revolve around use of Spring and/or Mockito both of which also amend bytecode/make additional classes)

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
  • 2,895
  • 18
  • 28
4

It is "return value mutator" of PIT (when return type is Object) and it is going to replace non-null return values with null and throw a java.lang.RuntimeException if the unmutated method would return null.

i.e mutated code:

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

Above mutator is expecting that your Junit should fail but for Runtime exception reason. assertNotNull(getTheObject()) is just to check whether return object is null or not and there is no way to get Runtime exception just by checking object value.

To kill this mutator you can call any method of that object (e.g getter()). Now if you call any method over null object (which is return by above muted code) then you will get null pointer exception (i.e Runtime exception) and your Junit will fail for muted code.

Ans:

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

Or

assertNotNull(getTheObject().getterOfAnyField());
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
srp
  • 619
  • 7
  • 18
  • Can you try to explain the answer a bit better? I for one do not see the connection between `assertThat(mutationTestService.getClassAObj(10).getA(),is(10));` and `getTheObject(){return null;}`. Also I don't understand why `assertNotNull` would not be sufficient to kill the mutator. Since the mutator returns `null`, `assertNotNull` should fail the unit test. What am I missing? Thanks! – Max Vollmer Oct 24 '19 at 10:43
  • @MaxVollmer I have improved my answer little bit. I hope it will be helpful for you.`Return value mutator` of pit is expecting test case should fail but for Runtime exception reason. Thanks – srp Nov 20 '19 at 07:21
  • Author of pitest here. Although in general you probably want tests that do more than assert that a return value is not null, a simple assertNotNull should be enough to kill this mutation, and this answer is therefore not correct. – henry Nov 21 '19 at 10:15