Skip to content

Commit 31c1c26

Browse files
authored
Migrate to assertThrows (#1826)
* Update JUnit to 4.13 and add default dependency on AssertJ. * Fix style issueswith tests and initial implementations. * Update affine-cipher to use assertThrows. * Migrate all-your-base to assertThrows. * Migrate alphametics to assertThrows. * Migrate bank-account to assertThrows. * Migrate binary-search to assertThrows. * Migrate bowling to assertThrows. * Migrate change to assertThrows. * Migrate circular-buffer to assertThrows. * Migrate collatz-conjecture to assertThrows. * Migrate dominoes to assertThrows. * Migrate error-handling to assertThrows. * Migrate forth to assertThrows. * Migrate go-counting to assertThrows. * Migrate grains to assertThrows. * Migrate hamming to assertThrows. * Migrate largest-series-product to assertThrows. * Migrate nth-prime to assertThrows. * Migrate nucleotide-count to assertThrows. * Migrate ocr-numbers to assertThrows. * Migrate palindrome-products to assertThrows. * Remove unused ExpectedException from pascals-triangle. * Migrate perfect-numbers to assertThrows. * Migrate phone-number to assertThrows. * Migrate queen-attack to assertThrows. * Migrate series to assertThrows. * Remove unused ExpectedException from simple-cipher. * Migrate simple-linked-list to assertThrows. * Migrate tree-building to assertThrows. * Migrate triangle to assertThrows. * Migrate variable-length-quantity to assertThrows. * Migrate wordy to assertThrows. * Update POLICIES to use assertThrows rather than ExpectedException. * Fix style violations. * Fix bowling tests and reference solution. * Restore dropped import for go-counting. * Fix exception for tree-building. * Fix style violation on bowling reference solution.
1 parent b2818e4 commit 31c1c26

File tree

35 files changed

+1178
-901
lines changed

35 files changed

+1178
-901
lines changed

POLICIES.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Our policies are not set-in-stone. They represent directions chosen at a point i
1717

1818
| Track Event | Policies to review |
1919
|:------------|:-----------------|
20-
| Exercise added/updated | [Prefer instance methods](#prefer-instance-methods); [Avoid using final](#avoid-using-final); [Adhere to best practices](#adhere-to-best-practices); [Starter implementations](#starter-implementations); [Ignore noninitial tests](#ignore-noninitial-tests); [Multiple file submissions](#multiple-file-submissions); [Name test class after class under test](#name-test-class-after-class-under-test); [Add hint for the first exercises without starter implementation](#add-hint-for-the-first-exercises-without-starter-implementation); [Reference tutorial in the first exercises](#reference-tutorial-in-the-first-exercises); [Avoid returning null](#avoid-returning-null); [Use ExpectedException](#use-expectedexception); [Using other assertion libraries](#using-other-assertion-libraries)
20+
| Exercise added/updated | [Prefer instance methods](#prefer-instance-methods); [Avoid using final](#avoid-using-final); [Adhere to best practices](#adhere-to-best-practices); [Starter implementations](#starter-implementations); [Ignore noninitial tests](#ignore-noninitial-tests); [Multiple file submissions](#multiple-file-submissions); [Name test class after class under test](#name-test-class-after-class-under-test); [Add hint for the first exercises without starter implementation](#add-hint-for-the-first-exercises-without-starter-implementation); [Reference tutorial in the first exercises](#reference-tutorial-in-the-first-exercises); [Avoid returning null](#avoid-returning-null); [Use assertThrows](#use-assertthrows); [Using other assertion libraries](#using-other-assertion-libraries)
2121
| Track rearranged | [Starter implementations](#starter-implementations); [Multiple file submissions](#multiple-file-submissions) |
2222
| New issue observed in track | [Good first issues](#good-first-issues) |
2323
| "Good first issue" issue completed | [Good first issues](#good-first-issues) |
@@ -149,14 +149,17 @@ References: [[1](https://github.com/exercism/java/issues/1389)]
149149
150150
References: [[1](https://www.codebyamir.com/blog/stop-returning-null-in-java)]
151151

152-
### Use ExpectedException
152+
### Use assertThrows
153153

154154
> Some exercises expect exceptions to be thrown in the tests.
155-
> The exercises on this track are all using JUnit's [`ExpectedException`](http://junit.org/junit4/javadoc/4.12/org/junit/rules/ExpectedException.html) `@Rule` feature to support that instead of `@Test(expected = SomeException.class)`.
156-
> `ExpectedException` is more powerful than using the `@Test` annotation, since with `ExpectedException` you can also inspect the exception's error message and other properties.
157-
> To be consistent, please use `ExpectedException` whenever you expect an exception to be thrown.
158-
159-
> See [the triangle tests](https://github.com/exercism/java/blob/master/exercises/triangle/src/test/java/TriangleTest.java) for an example of where `ExpectedException` is used.
155+
> The exercises on this track are all using [`org.junit.Assert.assertThrows`](https://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertThrows(java.lang.Class,%20org.junit.function.ThrowingRunnable)) instead of `@Test(expected = SomeException.class)`.
156+
> `assertThrows` is more powerful than using the `@Test` annotation.
157+
> With this method you can assert that a given function call (specified, for instance, as a lambda expression or method reference) results in a particular type of exception being thrown.
158+
> In addition it returns the exception that was thrown, so that further assertions can be made (e.g. to verify that the message and cause are correct).
159+
> Furthermore, you can make assertions on the state of a domain object after the exception has been thrown.
160+
> To be consistent, please use `assertThrows` whenever you expect an exception to be thrown.
161+
162+
> See [the triangle tests](https://github.com/exercism/java/blob/master/exercises/triangle/src/test/java/TriangleTest.java) for an example of where `assertThrows` is used.
160163
161164
References: [[1](https://github.com/junit-team/junit4/wiki/Exception-testing)]
162165

exercises/affine-cipher/src/test/java/AffineCipherTest.java

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,13 @@
1-
import org.junit.Before;
1+
import static org.assertj.core.api.Assertions.assertThat;
2+
import static org.junit.Assert.assertEquals;
3+
import static org.junit.Assert.assertThrows;
4+
25
import org.junit.Ignore;
3-
import org.junit.Rule;
46
import org.junit.Test;
5-
import org.junit.rules.ExpectedException;
6-
7-
import static org.junit.Assert.assertEquals;
87

98
public class AffineCipherTest {
109

11-
private AffineCipher affineCipher;
12-
13-
@Before
14-
public void genAffineCipher() {
15-
affineCipher = new AffineCipher();
16-
}
17-
18-
@Rule
19-
public ExpectedException expectedException = ExpectedException.none();
10+
private AffineCipher affineCipher = new AffineCipher();
2011

2112
@Test
2213
public void testEncodeYes() {
@@ -71,11 +62,14 @@ public void testEncodeAllTheLetters() {
7162

7263
@Ignore("Remove to run test")
7364
@Test
74-
public void testEncodeThrowsMeaningfulException() throws IllegalArgumentException {
75-
expectedException.expect(IllegalArgumentException.class);
76-
expectedException.expectMessage("Error: keyA and alphabet size must be coprime.");
65+
public void testEncodeThrowsMeaningfulException() {
66+
IllegalArgumentException expected =
67+
assertThrows(
68+
IllegalArgumentException.class,
69+
() -> affineCipher.encode("This is a test", 6, 17));
7770

78-
affineCipher.encode("This is a test", 6, 17);
71+
assertThat(expected)
72+
.hasMessage("Error: keyA and alphabet size must be coprime.");
7973
}
8074

8175
@Ignore("Remove to run test")
@@ -120,10 +114,13 @@ public void testDecodeWithTooManySpaces() {
120114
@Ignore("Remove to run test")
121115
@Test
122116
public void testDecodeThrowsMeaningfulException() {
123-
expectedException.expect(IllegalArgumentException.class);
124-
expectedException.expectMessage("Error: keyA and alphabet size must be coprime.");
117+
IllegalArgumentException expected =
118+
assertThrows(
119+
IllegalArgumentException.class,
120+
() -> affineCipher.decode("Test", 13, 5));
125121

126-
affineCipher.decode("Test", 13, 5);
122+
assertThat(expected)
123+
.hasMessage("Error: keyA and alphabet size must be coprime.");
127124
}
128125

129126
}

exercises/all-your-base/src/test/java/BaseConverterTest.java

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1+
import static org.assertj.core.api.Assertions.assertThat;
2+
import static org.junit.Assert.assertArrayEquals;
3+
import static org.junit.Assert.assertThrows;
4+
15
import org.junit.Ignore;
2-
import org.junit.Rule;
36
import org.junit.Test;
4-
import org.junit.rules.ExpectedException;
57

68
import java.util.Arrays;
79

8-
import static org.junit.Assert.assertArrayEquals;
9-
1010
public class BaseConverterTest {
1111

12-
@Rule
13-
public ExpectedException expectedException = ExpectedException.none();
14-
1512
@Test
1613
public void testSingleBitOneToDecimal() {
1714
BaseConverter baseConverter = new BaseConverter(2, new int[]{1});
@@ -218,79 +215,97 @@ public void testLeadingZeros() {
218215
@Ignore("Remove to run test")
219216
@Test
220217
public void testFirstBaseIsOne() {
221-
expectedException.expect(IllegalArgumentException.class);
222-
expectedException.expectMessage("Bases must be at least 2.");
218+
IllegalArgumentException expected =
219+
assertThrows(
220+
IllegalArgumentException.class,
221+
() -> new BaseConverter(1, new int[]{1}));
223222

224-
new BaseConverter(1, new int[]{1});
223+
assertThat(expected).hasMessage("Bases must be at least 2.");
225224
}
226225

227226
@Ignore("Remove to run test")
228227
@Test
229228
public void testFirstBaseIsZero() {
230-
expectedException.expect(IllegalArgumentException.class);
231-
expectedException.expectMessage("Bases must be at least 2.");
229+
IllegalArgumentException expected =
230+
assertThrows(
231+
IllegalArgumentException.class,
232+
() -> new BaseConverter(0, new int[]{1}));
232233

233-
new BaseConverter(0, new int[]{});
234+
assertThat(expected).hasMessage("Bases must be at least 2.");
234235
}
235236

236237
@Ignore("Remove to run test")
237238
@Test
238239
public void testFirstBaseIsNegative() {
239-
expectedException.expect(IllegalArgumentException.class);
240-
expectedException.expectMessage("Bases must be at least 2.");
240+
IllegalArgumentException expected =
241+
assertThrows(
242+
IllegalArgumentException.class,
243+
() -> new BaseConverter(-2, new int[]{1}));
241244

242-
new BaseConverter(-2, new int[]{});
245+
assertThat(expected).hasMessage("Bases must be at least 2.");
243246
}
244247

245248
@Ignore("Remove to run test")
246249
@Test
247250
public void testNegativeDigit() {
248-
expectedException.expect(IllegalArgumentException.class);
249-
expectedException.expectMessage("Digits may not be negative.");
251+
IllegalArgumentException expected =
252+
assertThrows(
253+
IllegalArgumentException.class,
254+
() -> new BaseConverter(2, new int[]{1, -1, 1, 0, 1, 0}));
250255

251-
new BaseConverter(2, new int[]{1, -1, 1, 0, 1, 0});
256+
assertThat(expected).hasMessage("Digits may not be negative.");
252257
}
253258

254259
@Ignore("Remove to run test")
255260
@Test
256261
public void testInvalidPositiveDigit() {
257-
expectedException.expect(IllegalArgumentException.class);
258-
expectedException.expectMessage("All digits must be strictly less than the base.");
262+
IllegalArgumentException expected =
263+
assertThrows(
264+
IllegalArgumentException.class,
265+
() -> new BaseConverter(2, new int[]{1, 2, 1, 0, 1, 0}));
259266

260-
new BaseConverter(2, new int[]{1, 2, 1, 0, 1, 0});
267+
assertThat(expected)
268+
.hasMessage("All digits must be strictly less than the base.");
261269
}
262270

263271
@Ignore("Remove to run test")
264272
@Test
265273
public void testSecondBaseIsOne() {
266-
BaseConverter baseConverter = new BaseConverter(2, new int[]{1, 0, 1, 0, 1, 0});
274+
BaseConverter baseConverter =
275+
new BaseConverter(2, new int[]{1, 0, 1, 0, 1, 0});
267276

268-
expectedException.expect(IllegalArgumentException.class);
269-
expectedException.expectMessage("Bases must be at least 2.");
277+
IllegalArgumentException expected =
278+
assertThrows(
279+
IllegalArgumentException.class,
280+
() -> baseConverter.convertToBase(1));
270281

271-
baseConverter.convertToBase(1);
282+
assertThat(expected).hasMessage("Bases must be at least 2.");
272283
}
273284

274285
@Ignore("Remove to run test")
275286
@Test
276287
public void testSecondBaseIsZero() {
277288
BaseConverter baseConverter = new BaseConverter(10, new int[]{7});
278289

279-
expectedException.expect(IllegalArgumentException.class);
280-
expectedException.expectMessage("Bases must be at least 2.");
290+
IllegalArgumentException expected =
291+
assertThrows(
292+
IllegalArgumentException.class,
293+
() -> baseConverter.convertToBase(0));
281294

282-
baseConverter.convertToBase(0);
295+
assertThat(expected).hasMessage("Bases must be at least 2.");
283296
}
284297

285298
@Ignore("Remove to run test")
286299
@Test
287300
public void testSecondBaseIsNegative() {
288301
BaseConverter baseConverter = new BaseConverter(2, new int[]{1});
289302

290-
expectedException.expect(IllegalArgumentException.class);
291-
expectedException.expectMessage("Bases must be at least 2.");
303+
IllegalArgumentException expected =
304+
assertThrows(
305+
IllegalArgumentException.class,
306+
() -> baseConverter.convertToBase(-7));
292307

293-
baseConverter.convertToBase(-7);
308+
assertThat(expected).hasMessage("Bases must be at least 2.");
294309
}
295310

296311
}

exercises/alphametics/src/test/java/AlphameticsTest.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
import static org.junit.Assert.assertEquals;
2+
import static org.junit.Assert.assertThrows;
23

34
import org.junit.Ignore;
4-
import org.junit.Rule;
55
import org.junit.Test;
6-
import org.junit.rules.ExpectedException;
76

87
import java.util.LinkedHashMap;
98

10-
119
public class AlphameticsTest {
12-
@Rule
13-
public ExpectedException expectedException = ExpectedException.none();
1410

1511
@Test
1612
public void testThreeLetters() throws UnsolvablePuzzleException {
@@ -24,16 +20,18 @@ public void testThreeLetters() throws UnsolvablePuzzleException {
2420

2521
@Ignore("Remove to run test")
2622
@Test
27-
public void testUniqueValue() throws UnsolvablePuzzleException {
28-
expectedException.expect(UnsolvablePuzzleException.class);
29-
new Alphametics("A == B").solve();
23+
public void testUniqueValue() {
24+
Alphametics alphametics = new Alphametics("A == B");
25+
26+
assertThrows(UnsolvablePuzzleException.class, alphametics::solve);
3027
}
3128

3229
@Ignore("Remove to run test")
3330
@Test
34-
public void testLeadingZero() throws UnsolvablePuzzleException {
35-
expectedException.expect(UnsolvablePuzzleException.class);
36-
new Alphametics("ACA + DD == BD").solve();
31+
public void testLeadingZero() {
32+
Alphametics alphametics = new Alphametics("ACA + DD == BD");
33+
34+
assertThrows(UnsolvablePuzzleException.class, alphametics::solve);
3735
}
3836

3937
@Ignore("Remove to run test")

0 commit comments

Comments
 (0)