afterEvaluate doesn't work for me

Hi,

I have a plugin where I have added:

println (“before afterEvaluate”)

project.afterEvaluate {

println (“in afterEvaluate”)

}

directly in the apply method.

Although I call project.afterEvaluate() in my unit test,

the first output is written to console, but the second not.

Are you using the ‘ProjectBuilder’ in your unit tests?

Hi Benjamin,

Yes, we are using a mechanism that uses ProjectBuilder itself with some additional general methods we have added. But internal we use the following API:

ProjectBuilder projectbuilder = ProjectBuilder.builder()

ProjectInternal project = projectbuilder.withName(“myTest”).build()

project.apply plugin: ‘ourOwnPlugin’

project.evaluate()

This works for me with Gradle 1.12. I haven’t tried it with 2.0 as well but I’d assume that it works as well.

This my plugin class:

import org.gradle.api.Project
import org.gradle.api.Plugin
  class MyPlugin implements Plugin<Project> {
    void apply(Project project) {
        println ("before afterEvaluate")
                   project.afterEvaluate {
             println ("in afterEvaluate")
         }
    }
}

This is my test class using the Spock framework:

import org.gradle.testfixtures.ProjectBuilder
import spock.lang.Specification
  class MyPluginTest extends Specification {
    def project = ProjectBuilder.builder().build()
          def "can call afterEvaluate"() {
        when:
        project.apply plugin: MyPlugin
        project.evaluate()
                  then:
        noExceptionThrown()
    }
}

In the report you should the output from ‘afterEvaluate’ in the tab ‘Standard output’.

I tried out your example, this works for gradle 2.0 as well - your right.

So i spend a little bit more of investigation and I find out that we are using

project.getTasksByName(‘classes’, true) in the plugin before the afterEvaluate block which leeds to this behavior.

Can you please double check it?

Do you know a valid fix?

Hi again,

have you checked it?

Should I open an issue, do you know an workaround?

Can you even reproduce it?

Cheers Markus

Yes, I can reproduce the issue with 2.0. This still worked in 1.12. I’d have to have a deeper look at the code to find out what has changed between both versions. I am going to open an issue if it happens to be a bug.

A reasonable alternative is to write integration tests with the help of the tooling API. However, it requires some setup on your end. For a quick start have a look nebula-test.

Puh - I don’t think using tooling API is no alternative for us at the moment, because we have to migrate more than 100 tests for this.

Is there another kind of workaround which is less effort?

Otherwise we have to wait for this bug is fixed in 2.1 :slight_smile:

Cheers Markus

Is it correct that you already had these tests written using ‘ProjectBuilder’ that used to work with 1.12? Now that you are trying to upgrade to 2.0, your tests are broken as ‘afterEvaluate’ is not called under certain circumstances?

We had these tests written using ProjectBuilder with 1.9, and we started to migrate to 1.12 - as I remember they worked with 1.12, too. So now we decided to migrate to 2.0 and skip the step to 1.12.

And now the all tests which wait for extensions to be filled don’t work anymore. Even other things are done in afterEvaluate().

I had a chance to have a look at the code in 2.0. The method ‘getTasksByName’ explicitly calls ‘evaluate’. Please have a look at AbstractProject. This means that evaluation happens before your ‘afterEvaluate’ is declared.

Depending on what you are trying to assert in your test case, you might just want look up the task(s) needed without using the method ‘getTasksByName’.

Hi Benjamin, thanks for your investigation, I fixed this issue by reimplementing getTasksByName in a utility class of our own.