This message was deleted.
# community-support
s
This message was deleted.
g
You'll likely have to do something like
(project as ProjectInternal).evaluate()
but I'm not sure if it will read gradle.properties
t
I figured something like that was in order. Ended up at this ugly thing instead
Copy code
given:
def stubProject = Stub(Project) {
  providers >> Stub(ProviderFactory) {
    gradleProperty('agpVersion') >> Stub(Provider) {
      getOrNull() >> agpVersion
      getOrElse(_) >> agpVersion
    }
    gradleProperty('square.agpVersion') >> Stub(Provider) {
      getOrNull() >> squareAgpVersion
      getOrElse(_) >> squareAgpVersion
    }
  }
}
d
In theory,
ProjectBuilder
is way pass the
gradle.properties
loading. Your best bet is to “fake” the loading of the
gradle.properties
and set the project properties directly on the project instead. However, I doubt the
providers.gradleProperty
is smart enough to figure that shortcut out.
ProjectBuilder
is basically, skipping the
settings.gradle
“_phase_” and goes straight to the
build.gradle
“_phase_”. Casting the project to
ProjectInternal
to evaluate is only good for faking the
afterEvaluate
actions. However, given it’s an internal API, your milage will vary. For example, using the redistribution Gradle JAR that I maintain (
dev.gradleplugins:gradle-api
) will fail starting 7.x because of how Gradle dynamically loads classpath at runtime. I reflected on the issue quite a bit and it’s quite hard to cleanly execute these type of test without going through the TestKit framework. To me,
ProjectBuilder
works at the integration test level. Stubbing/mocking is unfortunately, not the right “general” solution for unit testing as stubbing/mocking
Provider
, for example, is easy to get wrong (trust me I tried it). My current thinking is an optional mocking layer that behave like a
Project
(or
Settings
) instance without actually dispatching the action, etc. It allows tests to spy on the intent and not the implementation. However, even that approach blurs the line really quickly between a unit testing the smaller action units the plugin would uses and an integration test (and even functional testing). The issue comes when you define what you are trying to test. Passing parameters via Gradle properties is in some way an implementation details at the API level, but a behaviour at the functional level. For well defined action units, I would recommend to completely ejecting from Gradle APIs and use interface to communicate those Gradle properties.
1
If my memory is right, there is an internal service that takes care of the Gradle properties which is where the “injection” should happen but I don’t think you have much mutation control.
g
Thanks for detailed explanation. I used evaluate on ProjectInternal to test things done in the afterEvaluate blocks. Nowadays I usually go with TestKit for most of the tests
d
I also did the same, I'm actively moving toward extracting out the code from afterEvaluate or, as you mentioned, use TestKit.
t
thanks for that. In my case, I'm content with a bit of stubbing. It's a very simple test. Most of my gradle tests use TestKit, but it feels like overkill here
👍 1