Skip to content

New Feature: HttpClient Testing Support#15478

Closed
matrei wants to merge 23 commits into7.1.xfrom
feat/http-client-testing-support
Closed

New Feature: HttpClient Testing Support#15478
matrei wants to merge 23 commits into7.1.xfrom
feat/http-client-testing-support

Conversation

@matrei
Copy link
Copy Markdown
Contributor

@matrei matrei commented Mar 1, 2026

This pull request adds a new org.apache.grails:grails-testing-support-httpclient module and refactors the HTTP client usage in integration tests to use it, improving consistency and maintainability of test code.

@matrei matrei marked this pull request as draft March 1, 2026 12:15
@matrei matrei marked this pull request as ready for review March 5, 2026 14:09
@matrei matrei changed the title HttpClient testing support New Feature: HttpClient Testing Support Mar 5, 2026
@matrei matrei removed the maintenance label Mar 5, 2026
@matrei matrei moved this to In Progress in Apache Grails Mar 5, 2026
@matrei matrei requested a review from Copilot March 5, 2026 14:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new grails-testing-support-httpclient module (JDK HttpClient + Groovy extension assertions) and migrates multiple integration/functional tests across grails-test-examples/* to use the new support API, with corresponding dependency/doc/CI updates.

Changes:

  • Introduces grails-testing-support-httpclient (request helpers + HttpResponse fluent assertions + multipart builder) and publishes it.
  • Refactors many example integration tests to use HttpClientSupport instead of Micronaut’s HttpClient.
  • Updates docs and build/CI configuration to reflect the new module and test behavior.

Reviewed changes

Copilot reviewed 81 out of 81 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
settings.gradle Registers the new testing-support module in the build.
grails-testing-support-httpclient/build.gradle New module build with Groovy + JSON/XML + OpenTest4J dependency.
grails-testing-support-httpclient/src/main/groovy/org/apache/grails/testing/httpclient/MultipartBody.groovy Adds a multipart/form-data body builder for tests.
grails-testing-support-httpclient/src/main/resources/META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule Registers Groovy extension methods for HttpResponse.
grails-testing-support-httpclient/src/test/groovy/org/apache/grails/testing/httpclient/MultipartBodySpec.groovy Unit tests for multipart charset behavior.
grails-testing-support-httpclient/src/test/groovy/org/apache/grails/testing/httpclient/HttpResponseExtensionsSpec.groovy Unit tests for response assertion/parse extensions.
grails-testing-support-httpclient/src/test/groovy/org/apache/grails/testing/httpclient/HttpClientSupportSpec.groovy Unit tests for the HttpClientSupport trait helpers.
grails-test-examples/views-functional-tests/build.gradle Switches integration tests to depend on the new httpclient support module.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/api/NamespacedBookSpec.groovy Migrates to HttpClientSupport + fluent JSON assertions.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/VehicleSpec.groovy Migrates to HttpClientSupport and structured JSON checks.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/TestGsonControllerSpec.groovy Migrates to HttpClientSupport and expectJson/expectContains assertions.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/TestGmlControllerSpec.groovy Migrates to HttpClientSupport and xml() parsing.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/TestControllerSpec.groovy Migrates to HttpClientSupport and status/body assertions for 401.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/TeamSpec.groovy Migrates to HttpClientSupport and JSON assertions.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/ProxySpec.groovy Migrates to HttpClientSupport and header/body assertions.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/ProjectSpec.groovy Migrates to HttpClientSupport and response JSON extraction.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/ProductSpec.groovy Migrates product paging tests to new http helpers and assertions.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/PersonInheritanceSpec.groovy Migrates to HttpClientSupport and fluent checks.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/ObjectTemplateSpec.groovy Migrates to HttpClientSupport with status/body checks.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/ModelInterceptorIntSpec.groovy Migrates to HttpClientSupport for controller requests.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/InheritanceSpec.groovy Migrates to HttpClientSupport and JSON assertions.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/HttpClientSpec.groovy Removes legacy Micronaut HttpClient base spec.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/EmbeddedSpec.groovy Migrates embedded-domain rendering checks to new assertions.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/CustomerSpec.groovy Migrates to HttpClientSupport and with(response.json()) validations.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/CircularSpec.groovy Migrates circular rendering tests to new JSON/header assertions.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/BulletinSpec.groovy Migrates to HttpClientSupport and JSON parsing.
grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/BookSpec.groovy Migrates CRUD/error rendering tests to new http helpers.
grails-test-examples/micronaut/build.gradle Adds integration-test dependency on the new module.
grails-test-examples/micronaut/src/integration-test/groovy/micronaut/MicronautErsatzRoundtripSpec.groovy Replaces Micronaut client calls with HttpClientSupport requests.
grails-test-examples/micronaut/src/integration-test/groovy/micronaut/MicronautErsatzPatternSpec.groovy Replaces Micronaut client calls with new helpers.
grails-test-examples/micronaut/src/integration-test/groovy/micronaut/MicronautDeclarativeClientSpec.groovy Removes redundant Micronaut client roundtrip checks (keeps Ersatz/declarative client tests).
grails-test-examples/issue-views-182/build.gradle Switches integration tests to use new module dependency.
grails-test-examples/issue-views-182/src/integration-test/groovy/views182/HttpClientCommonSpec.groovy Removes legacy Micronaut client base spec.
grails-test-examples/issue-views-182/src/integration-test/groovy/views182/CustomErrorSpec.groovy Migrates to HttpClientSupport and status/body assertions.
grails-test-examples/issue-15228/build.gradle Switches integration tests to use new module dependency.
grails-test-examples/issue-15228/src/integration-test/groovy/issue11767/app/GsonViewRespondSpec.groovy Migrates to HttpClientSupport and JSON assertions.
grails-test-examples/issue-11767/build.gradle Adds integration-test dependency on new module; removes Micronaut client test deps.
grails-test-examples/issue-11767/src/integration-test/groovy/issue11767/app/ConfigLoadingSpec.groovy Migrates HTTP calls to HttpClientSupport.
grails-test-examples/issue-11102/build.gradle Adds integration-test dependency on new module; removes Micronaut client deps.
grails-test-examples/issue-11102/src/integration-test/groovy/issue11102/HttpClientCommonSpec.groovy Removes legacy Micronaut client base spec.
grails-test-examples/issue-11102/src/integration-test/groovy/issue11102/TestControllerSpec.groovy Migrates to HttpClientSupport and status/body assertions.
grails-test-examples/hibernate5/issue450/build.gradle Adds integration-test dependency on new module.
grails-test-examples/hibernate5/issue450/src/integration-test/groovy/example/BookControllerSpec.groovy Migrates to HttpClientSupport and fluent body assertions.
grails-test-examples/hibernate5/grails-multiple-datasources/build.gradle Adds integration-test dependency on new module; removes Micronaut client deps.
grails-test-examples/hibernate5/grails-multiple-datasources/src/integration-test/groovy/functionaltests/MultiDataSourceWithSessionSpec.groovy Migrates to HttpClientSupport and fluent body assertions.
grails-test-examples/demo33/build.gradle Adds integration-test dependency on new module.
grails-test-examples/demo33/src/integration-test/groovy/demo/JsonControllerSpec.groovy Migrates ad-hoc HTTP usage to HttpClientSupport.
grails-test-examples/cache/build.gradle Adds integration-test dependency on new module; removes Micronaut client deps.
grails-test-examples/cache/src/integration-test/groovy/com/demo/AdvancedCachingIntegrationSpec.groovy Migrates caching endpoint tests to new helper/JSON parsing.
grails-test-examples/async-events-pubsub-demo/build.gradle Adds integration-test dependency on new module; removes Micronaut client deps.
grails-test-examples/async-events-pubsub-demo/src/integration-test/groovy/pubsub/demo/TaskControllerSpec.groovy Migrates async error handling test to new helper.
grails-test-examples/app1/build.gradle Adds integration-test dependency on new module; removes Micronaut client test deps.
grails-test-examples/app1/src/integration-test/groovy/functionaltests/urlmappings/UrlMappingsSpec.groovy Migrates URL mapping integration tests to new helpers/assertions.
grails-test-examples/app1/src/integration-test/groovy/functionaltests/springevents/SpringEventsSpec.groovy Migrates Spring events endpoint tests to new helpers/assertions.
grails-test-examples/app1/src/integration-test/groovy/functionaltests/interceptors/InterceptorOrderingSpec.groovy Migrates interceptor endpoint tests to new helpers/assertions.
grails-test-examples/app1/src/integration-test/groovy/functionaltests/interceptors/InterceptorAdvancedMatchingSpec.groovy Migrates interceptor matching tests to new helpers/assertions.
grails-test-examples/app1/src/integration-test/groovy/functionaltests/flow/FlashChainForwardSpec.groovy Migrates flow tests, adds manual redirect handling with a no-redirect client.
grails-test-examples/app1/src/integration-test/groovy/functionaltests/errorhandling/ErrorHandlingSpec.groovy Migrates error-handling endpoint tests to new helpers/assertions.
grails-test-examples/app1/src/integration-test/groovy/functionaltests/cors/CorsAdvancedSpec.groovy Migrates CORS tests to new helpers/assertions.
grails-test-examples/app1/src/integration-test/groovy/functionaltests/caching/CachingSpec.groovy Migrates caching endpoint tests to new helpers/assertions.
grails-test-examples/app1/src/integration-test/groovy/functionaltests/async/AsyncPromiseSpec.groovy Migrates async endpoint tests to new helpers/assertions.
grails-test-examples/app1/src/integration-test/groovy/functionaltests/BookRestfulControllerSpec.groovy Migrates to HttpClientSupport and jsonList() parsing.
grails-test-examples/app1/src/integration-test/groovy/functionaltests/AtResourceSpec.groovy Migrates to HttpClientSupport and status assertions.
grails-doc/src/en/guide/testing/integrationTesting.adoc Documents the new httpclient testing support module and provides examples.
grails-doc/src/en/guide/introduction/whatsNew.adoc Adds “What’s New” entry for the new module.
gradle/publish-root-config.gradle Adds the new module to the list of published projects.
gradle/functional-test-config.gradle Tweaks Geb timeout property usage (comment clarifies default).
gradle.properties Adds openTest4jVersion for the new module dependency.
DEVELOPMENT.md Clarifies what gebAtCheckWaiting does.
.github/workflows/groovy-joint-workflow.yml Enables -PgebAtCheckWaiting for CI build job.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread grails-doc/src/en/guide/testing/integrationTesting.adoc
Copy link
Copy Markdown
Contributor

@jdaugherty jdaugherty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is such an incredible amount of work:

  1. it's a clear API
  2. it doesn't pollute our dependencies
  3. it's useful for all Grails apps and we adopted it ourselves (so the benefits are immediately clear in this PR)
  4. we own the API so we can enhance it more rapidly than Micronaut or Spring Boot

I have some minor concerns, mainly:

  1. the assumption is this is used in specs, but we're not following the recommended pattern for spec enhancement (using an extension)
  2. the naming - I'd like to propose an alternative with the assumption of a future addition
  3. could including this library with extensions cause a difference in behavior between prod/dev and test? Ancillary to this, I think using a delegate pattern may be better for testing, but I can definitely see the http client enhancements useful for a grails app itself. Interested to discuss this one.

Comment thread .github/workflows/groovy-joint-workflow.yml
Comment thread grails-doc/src/en/guide/introduction/whatsNew.adoc
Comment thread gradle/publish-root-config.gradle Outdated
Comment thread grails-testing-support-httpclient/build.gradle
@jdaugherty
Copy link
Copy Markdown
Contributor

I know this is a new feature, but i'd argue we should back port it. We don't have to announce it for 7.0.x, but the reason it should exist in 7.0.x is for easier maintenance given how much clean up on the tests have been done

@matrei
Copy link
Copy Markdown
Contributor Author

matrei commented Mar 6, 2026

Thank you @jdaugherty for excellent feedback!
I'm re-hauling the PR again, new changes coming soon.

@matrei matrei marked this pull request as draft March 6, 2026 13:27
matrei added 2 commits March 9, 2026 20:48
Add marker annotation for Spring test configuration classes that
should be auto-imported into Integration tests.
@matrei matrei force-pushed the feat/http-client-testing-support branch from 75d4501 to e1f1fb5 Compare March 9, 2026 20:59
@matrei matrei marked this pull request as ready for review March 9, 2026 21:59
@matrei matrei requested a review from Copilot March 10, 2026 08:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 92 out of 92 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread grails-doc/src/en/guide/testing/integrationTesting.adoc
Comment thread grails-testing-support-http-client/README.md Outdated
@Retention(RetentionPolicy.RUNTIME)
@Target([ElementType.TYPE])
@TestConfiguration(proxyBeanMethods = false)
@interface IntegrationTestAutoConfiguration {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So instead of a spock extension, you went with the bean approach. I assume that's why this change is now for 7.1.x instead of 7.0.x? I don't think it's a problem to use the test configuration approach, but can you give background on what led you down this path?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it is a new feature, it was always intended it for 7.1.x.
For proper IDE support I think we need an object to work with.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdaugherty So, a bit more context on why I went the @TestConfiguration route. I read here that using Traits on Specifications is not supported/recommended.

Now that I think about this some more, maybe this was overly cautious, as we apparently do that a lot already in Grails testing support:

  • UrlMappingsUnitTest
  • TagLibUnitTest
  • EnvironmentAwareSpec
  • GrailsUnitTest
  • GrailsWebUnitTest
  • DataTest
  • JsonViewTest
  • MocksDomains
  • etc.

I'll revert to using a trait...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My biggest concern of putting this in 7.1.x is this actually makes it easier to test grails-core. Would it be possible to put this in 7.0.x and only publish it in 7.1.x for external use? I want to make merges easier ...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that should be possible by referencing grails-testing-support-http-client as a project dependency instead of as a "usual" dependency in the test projects and remove it from publishing.

@matrei matrei changed the base branch from 7.1.x to 7.0.x March 13, 2026 14:27
# Conflicts:
#	grails-test-examples/app1/src/integration-test/groovy/functionaltests/async/AsyncPromiseSpec.groovy
@testlens-app
Copy link
Copy Markdown

testlens-app Bot commented Mar 13, 2026

🚨 TestLens detected 1 failed tests 🚨

Here is what you can do:

  1. Inspect the test failures carefully.
  2. If you are convinced that some of the tests are flaky, you can mute them below.
  3. Finally, trigger a rerun by checking the rerun checkbox.

Test Summary

Check Project/Task Test Runs
CI / Functional Tests (Java 17, indy=true) :grails-test-examples-scaffolding:integrationTest UserControllerSpec > User list

🏷️ Commit: 32a9787
▶️ Tests: 23355 executed
⚪️ Checks: 34/34 completed

Test Failure

UserControllerSpec > User list (:grails-test-examples-scaffolding:integrationTest in CI / Functional Tests (Java 17, indy=true))
geb.waiting.WaitTimeoutException: condition did not pass in 10 seconds (failed with exception)
	at geb.waiting.Wait.waitFor(Wait.groovy:128)
	at geb.waiting.PotentiallyWaitingExecutor.execute(PotentiallyWaitingExecutor.groovy:31)
	at geb.Page.verifyThisPageAtOnly(Page.groovy:424)
	at geb.Page.getAtVerificationResult(Page.groovy:217)
	at geb.Page.verifyAt(Page.groovy:188)
	at geb.Browser.doAt(Browser.groovy:1208)
	at geb.Browser.at(Browser.groovy:410)
	at geb.Browser.to(Browser.groovy:566)
	at geb.Browser.to(Browser.groovy:543)
	at geb.Browser.to(Browser.groovy:532)
	at grails.plugin.geb.support.delegate.BrowserDelegate$Trait$Helper.to(BrowserDelegate.groovy:160)
	at com.example.UserControllerSpec.User list(UserControllerSpec.groovy:46)
Caused by: Assertion failed: 

title == pageTitle
|     |  |
|     |  'User List'
|     false
'Please sign in'

	at com.example.pages.UserListPage._clinit__closure1(UserListPage.groovy:28)
	at com.example.pages.UserListPage._clinit__closure1(UserListPage.groovy)
	at geb.waiting.Wait.waitFor(Wait.groovy:117)
	... 11 more

Muted Tests

Select tests to mute in this pull request:

  • UserControllerSpec > User list

Reuse successful test results:

  • ♻️ Only rerun the tests that failed or were muted before

Click the checkbox to trigger a rerun:

  • Rerun jobs

Learn more about TestLens at testlens.app.

@jdaugherty
Copy link
Copy Markdown
Contributor

I see 7.1.x commits in the commit history for merging to 7.0.x @matrei

@matrei matrei changed the base branch from 7.0.x to 7.1.x March 14, 2026 16:17
@matrei
Copy link
Copy Markdown
Contributor Author

matrei commented Mar 14, 2026

Replaced by #15505

@matrei matrei closed this Mar 14, 2026
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Apache Grails Mar 14, 2026
@matrei matrei deleted the feat/http-client-testing-support branch March 23, 2026 12:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants