dtonhofer
Functional Programming in Java, Second Edition: Functional Programming in Java, Second Edition: JUnit code improvements for Chapter 11, pages 185 ff “Refactoring Unbounded Loops”
The same remarks apply as for “Refactoring the Traditional for Loop”
- No init()
- Negative tests which apply for input less than 1900, resulting in exceptions.
but we cannot implement a common interface as the method parameters change. So we wrap the new class into a class that obeys the old interface, which agains llaows us to use the same test code to test both odl and new classes.
There is also a little tweak to the semantics of the case where 1900 is already rejected - instead of returning 0, we throw. Because there basically is no result in that case.
package chapter11;
import org.junit.jupiter.api.Test;
import java.time.Year;
import java.util.function.Predicate;
import java.util.stream.IntStream;
import static org.junit.jupiter.api.Assertions.*;
public class UnboundedLoopTest {
interface Continue {
boolean check(int year);
}
interface WithContinue {
int countFrom1900(final Continue shouldContinue);
}
static class LeapYearsUnboundedBefore implements WithContinue {
public int countFrom1900(final Continue shouldContinue) {
if (!shouldContinue.check(1900)) {
throw new IllegalArgumentException("Cannot 'continue' right at the start!'");
}
int count = 0;
for (int year = 1900; ; year += 4) {
if (!shouldContinue.check(year)) {
break;
}
if (Year.isLeap(year)) {
count++;
}
}
return count;
}
}
// Does NOT implement WithContinue!!
static class LeapYearsUnboundedAfter {
public int countFrom1900(final Predicate<Integer> shouldContinue) {
if (!shouldContinue.test(1900)) {
throw new IllegalArgumentException("Cannot 'continue' right at the start!'");
}
return (int) IntStream.iterate(1900, year -> year + 4)
.takeWhile(shouldContinue::test)
.filter(Year::isLeap)
.count();
}
}
static class LeapYearsUnboundedAfterWrapped implements WithContinue {
private final LeapYearsUnboundedAfter ly;
public LeapYearsUnboundedAfterWrapped(LeapYearsUnboundedAfter ly) {
this.ly = ly;
}
public int countFrom1900(final Continue shouldContinue) {
return ly.countFrom1900(year -> shouldContinue.check(year));
}
}
// One should maybe have a separate method to test the throws
private static void commonLeapYearsTests(final WithContinue withContinue) {
assertAll(
() -> assertEquals(0, withContinue.countFrom1900(year -> year <= 1900)),
() -> assertEquals(25, withContinue.countFrom1900(year -> year <= 2000)),
() -> assertEquals(27, withContinue.countFrom1900(year -> year <= 2010)),
() -> assertEquals(31, withContinue.countFrom1900(year -> year <= 2025)),
() -> assertEquals(49, withContinue.countFrom1900(year -> year <= 2100)),
() -> assertEquals(267, withContinue.countFrom1900(year -> year <= 3000)),
() -> assertThrows(IllegalArgumentException.class, () ->
withContinue.countFrom1900(year -> year < 1800)
),
() -> assertThrows(IllegalArgumentException.class, () ->
withContinue.countFrom1900(year -> year < 1900)
)
);
}
@Test
void leapYearCountBefore() {
commonLeapYearsTests(new LeapYearsUnboundedBefore());
}
@Test
void leapYearCountAfter() {
commonLeapYearsTests(new LeapYearsUnboundedAfterWrapped(new LeapYearsUnboundedAfter()));
}
}
Popular Pragmatic Bookshelf topics
Python Testing With Pytest - Chapter 2, warnings for “unregistered custom marks”
While running the smoke tests in Chapter 2, I get these...
New
I thought that there might be interest in using the book with Rails 6.1 and Ruby 2.7.2. I’ll note what I needed to do differently here.
...
New
I can’t setup the Rails source code. This happens in a working directory containing multiple (postgres) Rails apps.
With:
ruby-3.0.0
s...
New
Hi! I know not the intentions behind this narrative when called, on page XI:
mount() |> handle_event() |> render()
but the correc...
New
In case this helps anyone, I’ve had issues setting up the rails source code. Here were the solutions:
In Gemfile, change
gem 'rails'
t...
New
When trying to generate the protobuf .go file, I receive this error:
Unknown flag: --go_opt
libprotoc 3.12.3
MacOS 11.3.1
Googling ...
New
I think I might have found a problem involving SwitchCompat, thumbTint, and trackTint.
As entered, the SwitchCompat changes color to hol...
New
I am using Android Studio Chipmunk | 2021.2.1 Patch 2
Build #AI-212.5712.43.2112.8815526, built on July 10, 2022
Runtime version: 11.0....
New
@mfazio23
Android Studio will not accept anything I do when trying to use the Transformations class, as described on pp. 140-141. Googl...
New
I’ve got to the end of Ch. 11, and the app runs, with all tabs displaying what they should – at first. After switching around between St...
New
Other popular topics
Write Elixir tests that you can be proud of. Dive into Elixir’s test philosophy and gain mastery over the terminology and concepts that u...
New
I know that these benchmarks might not be the exact picture of real-world scenario, but still I expect a Rust web framework performing a ...
New
Curious to know which languages and frameworks you’re all thinking about learning next :upside_down_face:
Perhaps if there’s enough peop...
New
You might be thinking we should just ask who’s not using VSCode :joy: however there are some new additions in the space that might give V...
New
Tailwind CSS is an exciting new CSS framework that allows you to design your site by composing simple utility classes to create complex e...
New
In case anyone else is wondering why Ruby 3 doesn’t show when you do asdf list-all ruby :man_facepalming: do this first:
asdf plugin-upd...
New
Author Spotlight
Jamis Buck
@jamis
This month, we have the pleasure of spotlighting author Jamis Buck, who has written Mazes for Prog...
New
Author Spotlight:
VM Brasseur
@vmbrasseur
We have a treat for you today! We turn the spotlight onto Open Source as we sit down with V...
New
I have always used antique keyboards like Cherry MX 1800 or Cherry MX 8100 and almost always have modified the switches in some way, like...
New
Big O Notation can make your code faster by orders of magnitude. Get the hands-on info you need to master data structures and algorithms ...
New
Categories:
Sub Categories:
Popular Portals
- /elixir
- /rust
- /ruby
- /wasm
- /erlang
- /phoenix
- /keyboards
- /python
- /js
- /rails
- /security
- /go
- /swift
- /vim
- /clojure
- /emacs
- /haskell
- /java
- /svelte
- /onivim
- /typescript
- /kotlin
- /crystal
- /c-plus-plus
- /tailwind
- /react
- /gleam
- /ocaml
- /elm
- /flutter
- /vscode
- /ash
- /html
- /opensuse
- /centos
- /zig
- /deepseek
- /php
- /scala
- /react-native
- /textmate
- /lisp
- /sublime-text
- /debian
- /nixos
- /agda
- /django
- /kubuntu
- /arch-linux
- /deno
- /ubuntu
- /revery
- /nodejs
- /spring
- /manjaro
- /lua
- /diversity
- /julia
- /markdown
- /c








