13

I have the following:

public class UnsetProperty extends Command {

    @Resource
    private SetProperty setProperty;

    public String parse(String[] args) {
        if (args.length != 4) {
            throw new RuntimeException("Incorrect number of arguments. Expected 4. Got " + args.length);
        }
        String publisher = args[0];
        String version = args[1];
        String mode = args[2];
        String property = args[3];

        /*
         * Unsetting a property is done by changing the current property to null.
         * Technically, the old property doesn't get changed, a new one is inserted with
         * a higher revision number, and it becomes the canonical one.
        */
        setProperty.setProperty(publisher, version, mode, property, null, false);
        return "";
    }
}

and the following test:

public class UnsetPropertyTest extends CommandTest {
    @Configuration
    public static class Config {

        @Bean(name = "mockSetProperty")
        public SetProperty getSetProperty() {
            return mock(SetProperty.class);
        }

        @Bean
        public UnsetProperty getUnsetProperty() {
            return new UnsetProperty();
        }

    }

    @Resource
    @InjectMocks
    private UnsetProperty unsetProperty;

    @Resource(name = "mockSetProperty")
    private SetProperty setProperty;

    // ... SNIP ...

    @Test
    public void testCallsSetPropertyWithCorrectParameters() throws SQLException, TaboolaException {
        final String[] args = new String[]{"publisher", "version", "mode", "property"};
        final String output = unsetProperty.parse(args);
        verify(setProperty).setProperty("publisher", "version", "mode", "property", null, false);
        // The above line should have killed the mutation!
        verifyNoMoreInteractions(setProperty);
        assertThat(output).isEqualTo("");
    }
}

The test passes, as expected. When I run it through PIT I get the following result

33   1. removed call to my/package/SetProperty::setProperty → SURVIVED

Line #33 is highlighted in the class code.

The tests examined are as follows:

  • my.package.UnsetPropertyTest.testCallsSetPropertyWithCorrectParameters(my.package.UnsetPropertyTest) (32 ms)
  • my.package.UnsetPropertyTest.testUnsetThrowsForIncorrectNumberOfParameters(my.package.UnsetPropertyTest) (3 ms)

Now:

  • When I change the test invoke parameters (args) the test fails. As expected
  • When I change the assertion (verify(setProperty).setProperty(...)) arguments the test fails. As expected.
  • When I manually comment out the function call highlighted in the first code block, the test fails.

Why does the mutation survive?

I'm using Java 8, Mockito 1.9.5 and PIT 1.1.4.

Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308

1 Answers1

1

Years later but no one seemed to mention that (Spring) @Resource and (Mockito) @InjectMocks are mutually exclusive solutions. You have multiple generated subclasses of UnsetProperty in play so PIT is simply confused about what's going on.

drekbour
  • 2,895
  • 18
  • 28
  • I am no longer in a position to test your answer (4.5 years *is* a long time), but hopefully someone else facing the same problem will. – Madara's Ghost Oct 28 '19 at 08:05