@@ -50,20 +50,20 @@ so that the whole test method reads
5050[source,java]
5151----
5252@ParameterizedTest
53- @CsvSource( {
53+ @CsvSource({
5454 "a,greenCircle,blueCircle,500.0,400.0,100.0,100.0,500.0",
5555 "b,redCircle,blueCircle,400.0,100.0,100.0,100.0,500.0",
56- "c,greenCircle,redCircle,300.0,100.0,100.0,400.0,100.0", } )
57- public void tLength( String line, String p1, String p2, double expected,
58- double x1, double y1, double x2, double y2 ) throws ParseException {
56+ "c,greenCircle,redCircle,300.0,100.0,100.0,400.0,100.0", })
57+ public void tLength(String line, String p1, String p2, double expected,
58+ double x1, double y1, double x2, double y2) throws ParseException {
5959 double xOrg = stage.getX();
6060 double yOrg = stage.getY();
6161 FxRobot rob = new FxRobot();
62- rob.drag( '#' + p1 ).dropTo( xOrg + x1, yOrg + y1 );
63- rob.drag( '#' + p2 ).dropTo( xOrg + x2, yOrg + y2 );
64- String ltext = labelMap.get( line ).apply( triangulator ).getText();
65- double l = getDoubleConsideringLocale( ltext.split( ":" )[ 1 ] ); // <1>
66- assertThat( l ).isCloseTo( expected, within( 0.1 ) );
62+ rob.drag('#' + p1).dropTo(xOrg + x1, yOrg + y1);
63+ rob.drag('#' + p2).dropTo(xOrg + x2, yOrg + y2);
64+ String ltext = labelMap.get(line).apply(triangulator).getText();
65+ double l = getDoubleConsideringLocale(ltext.split(":")[1] ); // <1>
66+ assertThat(l ).isCloseTo(expected, within(0.1) );
6767// fail( "method tLength reached end. You know what to do." );
6868}
6969----
@@ -79,9 +79,9 @@ public void tLength( String line, String p1, String p2, double expected,
7979 * @return the double
8080 * @throws ParseException if the string does not parse to double.
8181 */
82- static double getDoubleConsideringLocale( String input )
82+ static double getDoubleConsideringLocale(String input)
8383 throws ParseException {
84- return DecimalFormat.getNumberInstance().parse( input ).doubleValue(); // <1>
84+ return DecimalFormat.getNumberInstance().parse(input).doubleValue(); // <1>
8585}
8686
8787/**
@@ -91,14 +91,9 @@ static double getDoubleConsideringLocale( String input )
9191* @return the double.
9292* @throws ParseException if the string does not parse to double.
9393*/
94- <<<<<<< Updated upstream
95- static double getDoubleConsideringLocale( Locale locale, String input )
94+ static double getDoubleConsideringLocale(Locale locale, String input)
9695 throws ParseException {
97- =======
98- static double getDoubleConsideringLocale( Locale locale, String input )
99- throws ParseException {
100- >>>>>>> Stashed changes
101- return DecimalFormat.getNumberInstance(locale).parse( input ).doubleValue();
96+ return DecimalFormat.getNumberInstance(locale).parse(input).doubleValue();
10297}
10398----
10499
@@ -107,12 +102,54 @@ static double getDoubleConsideringLocale( Locale locale, String input )
107102.Set the locale for the execution. Useful for tests.
108103[source,java]
109104----
110- Locale.setDefault( Locale.GERMANY ); // <1>
105+ Locale.setDefault(Locale.GERMANY); // <1>
111106----
112107
113108<1> Set the locale to GERMANY if it isn't already. Similar for other languages.
114109
115110
111+ === ResourceBundle and MessageFormat
112+
113+ Java's `ResourceBundle` is the standard mechanism for externalising locale-specific strings into `.properties` files.
114+ Place one base file plus one file per supported locale under `src/main/resources`:
115+
116+ ----
117+ src/main/resources/pub/inthepub.properties ← default (English)
118+ src/main/resources/pub/inthepub_nl_NL.properties ← Dutch
119+ src/main/resources/pub/inthepub_de_DE.properties ← German
120+ ----
121+
122+ A `.properties` file is a plain key=value text file.
123+ Keys that contain `{0}`, `{1}`, … are parameterised placeholders:
124+
125+ .greetings.properties
126+ [source,properties]
127+ ----
128+ greeting=Hello, {0}!
129+ farewell=Goodbye, {0}. See you on {1}.
130+ ----
131+
132+ To load the bundle for the current locale and look up a key at runtime:
133+
134+ .Looking up and formatting a localized message
135+ [source,java]
136+ ----
137+ ResourceBundle bundle = ResourceBundle.getBundle(
138+ "greetings", // <1>
139+ Locale.getDefault()); // <2>
140+ if (bundle.containsKey("greeting")) { // <3>
141+ String pattern = bundle.getString("greeting");
142+ String message = MessageFormat.format(pattern, "World"); // <4>
143+ }
144+ ----
145+
146+ <1> Base name of the properties file (no extension, no locale suffix) — Java appends `_nl_NL` etc. automatically.
147+ <2> Use the current default locale. Change it with `Locale.setDefault(...)`, e.g. in a test.
148+ <3> `containsKey` guards against `MissingResourceException` when a key is absent.
149+ <4> `MessageFormat.format` substitutes `{0}`, `{1}`, … with the supplied arguments.
150+
151+ The JVM picks the most specific file available: `inthepub_nl_NL.properties` → `inthepub_nl.properties` → `inthepub.properties` (fallback).
152+
116153=== Testing Localized Exceptions
117154
118155The standard way of testing exceptions with assertj is explained in link:week01.html#_assert_exceptions[week01].
@@ -121,23 +158,22 @@ To get to the localized message, which contains the message as translated by the
121158
122159Luckily, AssertJ allows you to extract information from a Throwable, by using an extractor function. Now the Lambda bells should ring.
123160
124- .To make a long story very short: here is an example:
161+ .To make a long story very short: here is an example (using the pub exercise domain) :
125162[source,java]
126163----
127- String[] keys = keyWords.split( "\\|");
128- assertThatThrownBy( () -> {
129- MainSimulation.main( args );
130- } ).isExactlyInstanceOf( exceptionMap.get( expectionClassName ) )
131- .extracting( e -> e.getLocalizedMessage() ) // <1>
164+ Locale.setDefault(Locale.forLanguageTag("nl-NL"));
165+ assertThatThrownBy(() -> barkeeper.serve(drinker, volume))
166+ .isExactlyInstanceOf(EmptyStockException.class)
167+ .extracting(e -> e.getLocalizedMessage()) // <1>
132168 .asString() //<2>
133- .contains( keys ); //<3>
169+ .contains("uitverkocht" ); //<3>
134170----
135171
136172<1> extract using [blue]`Function<? super Throwable,T>`, [black]`e -> getLocalizedMessage()` in this case.
137173<2> Get the assertion for in String. Do [red]*not* use `toString()`, because that produces a _String_, not an [blue]*AbstractStringAssert*.
138174<3> And use the assert to check that the string contains the required key information.
139175
140- .If you turn on type hints in NetBeans-IDE (or in vscode/intelij ) you can see what the type is on which you call `contains(keys)`
176+ .If you turn on type hints in NetBeans-IDE (or in VS Code/IntelliJ ) you can see what the type is on which you call `contains(keys)`
141177image::assertjtypehints.png
142178
143179
0 commit comments