Slackbot
05/06/2022, 6:50 PMgrossws
05/06/2022, 7:13 PM(project as ProjectInternal).evaluate() but I'm not sure if it will read gradle.propertiestony
05/06/2022, 7:26 PMgiven:
def stubProject = Stub(Project) {
providers >> Stub(ProviderFactory) {
gradleProperty('agpVersion') >> Stub(Provider) {
getOrNull() >> agpVersion
getOrElse(_) >> agpVersion
}
gradleProperty('square.agpVersion') >> Stub(Provider) {
getOrNull() >> squareAgpVersion
getOrElse(_) >> squareAgpVersion
}
}
}daniel
05/07/2022, 12:33 AMProjectBuilder 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.daniel
05/07/2022, 12:35 AMgrossws
05/07/2022, 4:14 PMdaniel
05/07/2022, 4:44 PMtony
05/07/2022, 9:01 PM