@@ -3824,3 +3824,117 @@ include::{testDir}/example/AutoCloseDemo.java[tags=user_guide_example]
38243824<1> Annotate an instance field with `@AutoClose`.
38253825<2> `WebClient` implements `java.lang.AutoCloseable` which defines a `close()` method that
38263826 will be invoked after each `@Test` method.
3827+
3828+ [[writing-tests-built-in-extensions-DefaultLocaleAndTimeZone]]
3829+ ==== The @DefaultLocale and @DefaultTimeZone Extensions
3830+
3831+ The `{DefaultLocale}` and `{DefaultTimeZone}` annotations can be used to change the values
3832+ returned from `Locale.getDefault()` and `TimeZone.getDefault()`, respectively, which are
3833+ often used implicitly when no specific locale or time zone is chosen. Both annotations
3834+ work on the test class level and on the test method level, and are inherited from
3835+ higher-level containers. After the annotated element has been executed, the initial
3836+ default value is restored.
3837+
3838+ [[writing-tests-built-in-extensions-DefaultLocale]]
3839+ ===== @DefaultLocale
3840+
3841+ The default `Locale` can be specified using an
3842+ {jdk-javadoc-base-url}/java.base/java/util/Locale.html#forLanguageTag-java.lang.String-[IETF BCP 47 language tag string].
3843+
3844+ [source,java,indent=0]
3845+ ----
3846+ include::{testDir}/example/DefaultLocaleTimezoneExtensionDemo.java[tags=default_locale_language]
3847+ ----
3848+
3849+ Alternatively, the default `Locale` can be created using the following attributes from
3850+ which a {jdk-javadoc-base-url}/java.base/java/util/Locale.Builder.html[`Locale.Builder`]
3851+ can create an instance:
3852+
3853+ * `language` or
3854+ * `language` and `country` or
3855+ * `language`, `country`, and `variant`
3856+
3857+ NOTE: The variant needs to be a string which follows the
3858+ https://www.rfc-editor.org/rfc/rfc5646.html[IETF BCP 47 / RFC 5646] syntax
3859+
3860+ [source,java,indent=0]
3861+ ----
3862+ include::{testDir}/example/DefaultLocaleTimezoneExtensionDemo.java[tag=default_locale_language_alternatives]
3863+ ----
3864+
3865+ Mixing language tag configuration (via the annotation's `value` attributed) and
3866+ attributed-based configuration will cause an exception to be thrown. Furthermore, a
3867+ `variant` can only be specified if `country` is also specified. Otherwise, an exception
3868+ will be thrown.
3869+
3870+ Any method-level `@DefaultLocale` configurations will override class-level configurations.
3871+
3872+ [source,java,indent=0]
3873+ ----
3874+ include::{testDir}/example/DefaultLocaleTimezoneExtensionDemo.java[tag=default_locale_class_level]
3875+ ----
3876+
3877+ NOTE: A class-level configuration means that the specified locale is set before and reset
3878+ after each individual test in the annotated class.
3879+
3880+ If your use case is not covered, you can implement the `{LocaleProvider}` interface.
3881+
3882+ [source,java,indent=0]
3883+ ----
3884+ include::{testDir}/example/DefaultLocaleTimezoneExtensionDemo.java[tag=default_locale_with_provider]
3885+ ----
3886+
3887+ NOTE: The provider implementation must have a no-args (or the default) constructor.
3888+
3889+ [[writing-tests-built-in-extensions-DefaultTimeZone]]
3890+ ===== @DefaultTimeZone
3891+
3892+ The default `TimeZone` is specified according to the
3893+ {jdk-javadoc-base-url}/java.base/java/util/TimeZone.html#getTimeZone(java.lang.String)[TimeZone.getTimeZone(String)]
3894+ method.
3895+
3896+ [source,java,indent=0]
3897+ ----
3898+ include::{testDir}/example/DefaultLocaleTimezoneExtensionDemo.java[tag=default_timezone_zone]
3899+ ----
3900+
3901+ Any method level `@DefaultTimeZone` configurations will override class level configurations:
3902+
3903+ [source,java,indent=0]
3904+ ----
3905+ include::{testDir}/example/DefaultLocaleTimezoneExtensionDemo.java[tag=default_timezone_class_level]
3906+ ----
3907+
3908+ NOTE: A class-level configuration means that the specified time zone is set before and
3909+ reset after each individual test in the annotated class.
3910+
3911+ If your use case is not covered, you can implement the `{TimeZoneProvider}` interface.
3912+
3913+ [source,java,indent=0]
3914+ ----
3915+ include::{testDir}/example/DefaultLocaleTimezoneExtensionDemo.java[tag=default_time_zone_with_provider]
3916+ ----
3917+
3918+ NOTE: The provider implementation must have a no-args (or the default) constructor.
3919+
3920+ ===== Thread Safety
3921+
3922+ Since the default locale and time zone are global state, reading and writing them during
3923+ <<writing-tests-parallel-execution, parallel test execution>> can lead to unpredictable
3924+ results and flaky tests. The `@DefaultLocale` and `@DefaultTimeZone` extensions are
3925+ prepared for that and tests annotated with them will never execute in parallel (thanks to
3926+ `{ResourceLock}`) to guarantee correct test results.
3927+
3928+ However, this does not cover all possible cases. Tested code that reads or writes default
3929+ locale and time zone _independently_ of the extensions can still run in parallel to them
3930+ and may thus behave erratically when, for example, it unexpectedly reads a locale set by
3931+ the extension in another thread. Tests that cover code that reads or writes the default
3932+ locale or time zone need to be annotated with the respective annotation:
3933+
3934+ * `{ReadsDefaultLocale}`
3935+ * `{ReadsDefaultTimeZone}`
3936+ * `{WritesDefaultLocale}`
3937+ * `{WritesDefaultTimeZone}`
3938+
3939+ Tests annotated in this way will never execute in parallel with tests annotated with
3940+ `@DefaultLocale` or `@DefaultTimeZone`.
0 commit comments