Search code examples
javaspock

Using IntelliJ an unchanged spock test will begin taking a long time to complete, if at all


I am using IntelliJ with java/gradle/spock unit tests.

Upon making changes to any code the build runs the whole suite of unit tests and it has come to a well known timing. Build takes 2:xx and testing takes 8:xx minutes

At some point, the tests will far exceed this amount of time and usually one would have to reboot and/or clear caching and so forth.

In this last incidence, I used @Ignore to clear all the tests from one particular file. This corrected the timing, and I added each one back in by removing the @Ignore. Most tests would run immediately in a very short time. I have come down to 3 tests that when added will bring back this long running behavior.

We have seen this issue in the past, and usually it is corrected by "magic". (Things like, clearing cache, freeing memory, rebooting a computer, and other hard to associate things).

My question is, if someone has experienced this and knows a fix? Or, if someone can point me in a direction to actually investigate what is going on so that I can better dig into it. I will be trying setting some debug break points and things like that today. But anything else that I may be overlooking or unaware of like settings of things like that would be helpful.

Tried: Restarting, clearing of cache, rebooting. Expected: Spontaneous correction. Experienced: Continued failure.

Tried: Isolate UT's using @Ignore Expected: Spontaneous correction. Experienced: Success

Tried: Reintroducing @Ignored tests Expected: Locate correlated causative tests Experienced: 3 tests when added back in will each cause this similar behavior


Solution

  • Thanks for anyone who took the time to look at this. I apologize that it was poorly submitted, but due to the nature of it, it would have been prohibitively difficult to create something that could be more accurate.

    The cause was due to declaring a variable as a Mono then setting it to Mock(). Even though stubs were written for its members, this does not go through project reactor reactor chains and in so bouncing out, causes a long hang, that seems never to actually complete.

    Here is a "genericized" code illustration that hopefully will help someone doing the same mistake that I did.

    // The existing code looked something like this, however it was
    // spread out among class variables, and setup() method and 
    // given/when/then sections of the UTs. 
    // Declare a variable
    Mono<ClassVar> classVar 
    // that is mocked
    classVar = Mock()
    // create an expected member variable
    MemberType member = new MemberType()
    // stub the mocked class to return the member variable
    classVar.getMember() >> member
    // When the reactive chains encounter this, they go off into 
    // what feels like a forever grind... 
    
    // The correction involved restructuring things like this;
    // Declare a variable
    Mono<ClassVar> classVar 
    // create an minimal inner payload for it (I think this could still be
    // a Mock() though I decided to simplify at the same time)
    ClassVar classVarValue = new ClassVar()
    // create the expect member variable
    MemberType member = new MemberType()
    // place it into the minimal inner payload variable
    classVarValue.setMember(member)
    // populate the initial variable with the result of a Mono.just() call
    // that contains the minimal inner payload variable
    classVar = Mono.just(classVarValue)
    

    I could have done this with more mocking, but the issue is that you can't do

    Mono something = Mock()

    I am not sure if you can do Mono something = Mono.just(Mock())

    But I suspect that would have worked out. I avoided that by declaring a variable that was sparse, and creating the Mono<> from that.