Search code examples
unit-testinggrailsmockingspock

Cannot mock static Groovy method when using '@CompileStatic'


I'm trying to mock a static helper class (ConfigHelper) which returns config values. This has worked before in many other tests, but fails in my newest Spock test for some reason.

The service I'm testing is the following:

<redacted>
import grails.plugin.cache.Cacheable
import groovy.transform.CompileStatic

import javax.annotation.PostConstruct

@CompileStatic
class AssetsIntegrationService extends ExternalDiagnosticService {

    static String urlTilErstLogo() {
        return ConfigHelper.hentConfig(ConfigNoegler.ERST_LOGO_URL)
    }

    @Cacheable(value = 'erst-logo')
    String hentErstLogoSomBase64Streng() {
        String url = urlTilErstLogo()  // returns null
        String url2 = ConfigHelper.hentConfig(ConfigNoegler.ERST_LOGO_URL) // returns null
        return getByteArrayFromImageURL(url)
    }

    private static String getByteArrayFromImageURL(String url) {
        URL imageUrl = new URL(url)
        URLConnection ucon = imageUrl.openConnection()
        InputStream is = ucon.getInputStream()
        ByteArrayOutputStream baos = new ByteArrayOutputStream()
        byte[] buffer = new byte[1024]
        int read = 0
        while ((read = is.read(buffer, 0, buffer.length)) != -1) {
            baos.write(buffer, 0, read)
        }
        baos.flush()
        return Base64.getEncoder().encodeToString(baos.toByteArray())
    }
}

And my spock test:

<redacted>
import grails.testing.gorm.DataTest
import grails.testing.services.ServiceUnitTest
import spock.lang.Specification

class AssetsIntegrationServiceSpec extends Specification implements DataTest, ServiceUnitTest<AssetsIntegrationService>{

    def setup() {
        GroovyMock(ConfigHelper, global: true)
        ConfigHelper.hentConfig(ConfigNoegler.ERST_LOGO_URL) >> "https://url.com"
    }

    def "hentErstLogoSomBase64Streng"() {
        when:
            String res = service.hentErstLogoSomBase64Streng()
        then:
            noExceptionThrown()
    }
}

It seems like my mock is ignored, because ConfigHelper.hentConfig(ConfigNoegler.ERST_LOGO_URL) simply returns null in my service. However, if I set a breakpoint in the service and try calling ConfigHelper.hentConfig(ConfigNoegler.ERST_LOGO_URL) from the IntelliJ expression evaluator, the correct mocked url is retured!


Solution

  • The problem is caused by @CompileStatic just remove it, or replace it by @TypeChecked.

    It is the same problem I've explained here already: https://stackoverflow.com/a/59481265/2145769