From c6a6db3b74015ace3daee8814b91888530dd6c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Bla=C5=BEevi=C4=87?= Date: Tue, 25 Nov 2025 01:25:28 +0100 Subject: [PATCH] [BAEL-9374] A Guide to @ClassTemplate in JUnit 5 - implement class template that runs date-formatting tests under multiple locales --- .../classtemplate/extended/DateFormatter.java | 16 ++++++++ .../extended/DateFormatterLocaleUnitTest.java | 39 +++++++++++++++++++ .../DateLocaleClassTemplateProvider.java | 39 +++++++++++++++++++ .../extended/LocaleExtension.java | 29 ++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 testing-modules/junit-5-advanced-3/src/main/java/com/baeldung/classtemplate/extended/DateFormatter.java create mode 100644 testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/DateFormatterLocaleUnitTest.java create mode 100644 testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/DateLocaleClassTemplateProvider.java create mode 100644 testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/LocaleExtension.java diff --git a/testing-modules/junit-5-advanced-3/src/main/java/com/baeldung/classtemplate/extended/DateFormatter.java b/testing-modules/junit-5-advanced-3/src/main/java/com/baeldung/classtemplate/extended/DateFormatter.java new file mode 100644 index 000000000000..2dd74ae5cb91 --- /dev/null +++ b/testing-modules/junit-5-advanced-3/src/main/java/com/baeldung/classtemplate/extended/DateFormatter.java @@ -0,0 +1,16 @@ +package com.baeldung.classtemplate.extended; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; +import java.util.Locale; + +class DateFormatter { + + public String format(LocalDate date) { + DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG) + .withLocale(Locale.getDefault()); + + return date.format(formatter); + } +} diff --git a/testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/DateFormatterLocaleUnitTest.java b/testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/DateFormatterLocaleUnitTest.java new file mode 100644 index 000000000000..e112fdb43663 --- /dev/null +++ b/testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/DateFormatterLocaleUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.classtemplate.extended; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; +import java.util.Locale; + +import org.junit.jupiter.api.ClassTemplate; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ClassTemplate +@ExtendWith(DateLocaleClassTemplateProvider.class) +class DateFormatterLocaleUnitTest { + + private static final Logger LOG = LoggerFactory.getLogger(DateFormatterLocaleUnitTest.class); + + private final DateFormatter formatter = new DateFormatter(); + + @Test + void givenDefaultLocale_whenFormattingDate_thenMatchesLocalizedOutput() { + LocalDate date = LocalDate.of(2025, 9, 30); + + DateTimeFormatter expectedFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG) + .withLocale(Locale.getDefault()); + + String expected = date.format(expectedFormatter); + String formatted = formatter.format(date); + + LOG.info("Locale: {}, Expected: {}, Formatted: {}", Locale.getDefault(), expected, formatted); + + assertEquals(expected, formatted); + } + +} diff --git a/testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/DateLocaleClassTemplateProvider.java b/testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/DateLocaleClassTemplateProvider.java new file mode 100644 index 000000000000..ddca7d649b0c --- /dev/null +++ b/testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/DateLocaleClassTemplateProvider.java @@ -0,0 +1,39 @@ +package com.baeldung.classtemplate.extended; + +import java.util.List; +import java.util.Locale; +import java.util.stream.Stream; + +import org.junit.jupiter.api.extension.ClassTemplateInvocationContext; +import org.junit.jupiter.api.extension.ClassTemplateInvocationContextProvider; +import org.junit.jupiter.api.extension.Extension; +import org.junit.jupiter.api.extension.ExtensionContext; + +class DateLocaleClassTemplateProvider implements ClassTemplateInvocationContextProvider { + + @Override + public boolean supportsClassTemplate(ExtensionContext context) { + return true; + } + + @Override + public Stream provideClassTemplateInvocationContexts(ExtensionContext context) { + return Stream.of(invocationContext(Locale.US), invocationContext(Locale.GERMANY), invocationContext(Locale.ITALY), invocationContext(Locale.JAPAN)); + } + + private ClassTemplateInvocationContext invocationContext(Locale locale) { + return new ClassTemplateInvocationContext() { + + @Override + public String getDisplayName(int invocationIndex) { + return "Locale: " + locale.getDisplayName(); + } + + @Override + public List getAdditionalExtensions() { + return List.of(new LocaleExtension(locale)); + } + }; + } +} + diff --git a/testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/LocaleExtension.java b/testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/LocaleExtension.java new file mode 100644 index 000000000000..ba036cce2f52 --- /dev/null +++ b/testing-modules/junit-5-advanced-3/src/test/java/com/baeldung/classtemplate/extended/LocaleExtension.java @@ -0,0 +1,29 @@ +package com.baeldung.classtemplate.extended; + +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +import java.util.Locale; + +class LocaleExtension implements BeforeEachCallback, AfterEachCallback { + + private final Locale locale; + private Locale previous; + + public LocaleExtension(Locale locale) { + this.locale = locale; + } + + @Override + public void beforeEach(ExtensionContext context) { + previous = Locale.getDefault(); + Locale.setDefault(locale); + } + + @Override + public void afterEach(ExtensionContext context) { + Locale.setDefault(previous); + } +} +