joke / spock-mockable

Mock the un-mockable
Apache License 2.0
28 stars 2 forks source link

Both are executed when Mock Static void method #355

Closed rosincc closed 1 year ago

rosincc commented 1 year ago

The following example will pass the test:

final class Static {
    public static void tVoid() {
        throw new UnsupportedOperationException();
    }
}

class StaticTest extends Specification {
    def 'tVoid'() {
        given:
        def runMock = []
        Spy(Static)
        Static.tVoid() >> {runMock << true}

        when:
        Static.tVoid()

        then:
        runMock[0] == true
        thrown(UnsupportedOperationException)
    }
}
joke commented 1 year ago

@hellsof the interaction needs to be added to the then block. Otherwise you are still executing the method and shifting it. Same goes for non static methods.

rosincc commented 1 year ago

There is no such problem after trying the non-static method, can you give a correct sample code, thanks.

joke commented 1 year ago

@hellsof I didn't get the problem you were talking about. But now I understand. You are absolutely right there is a bug in the interception code.

rosincc commented 1 year ago

Yes, an exception should not be thrown here, but it is thrown when it is actually executed, causing the above test case to pass the test.

rosincc commented 1 year ago

Perhaps the following example can better demonstrate this problem:

final class Static {
    public static void tVoid(List<String> list) {
        list.add("old");
    }
}

class StaticTest extends Specification {
    def 'tVoid'() {
        given:
        Spy(Static)
        List<String> param = new ArrayList<>()

        when:
        Static.tVoid(param)

        then:
        1 * Static.tVoid(_) >> {ArrayList<String> list ->
            list << "mock"
        }

        expect:
        param == ["mock"] // Condition not satisfied: param=["mock", "old"]
    }
joke commented 1 year ago

@hellsof The problem should be fixed now. Thanks for reporting the problem