 
  		        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
                         
                      
                       
          
                This test is broken right out of the box… 
— FAIL: TestAgent (7.82s) 
agent_test.go:77: 
Error Trace:    agent_test.go:77 
agent_test.go:...
              
            
            
          
              New
 
          
                Python Testing With Pytest - Chapter 2, warnings for “unregistered custom marks” 
While running the smoke tests in Chapter 2, I get these...
              
            
            
          
              New
 
          
                On the page xv there is an instruction to run bin/setup from the main folder. I downloaded the source code today (12/03/21) and can’t see...
              
            
            
          
              New
 
          
                The generated iex result below should list products instead of product for the metadata. (page 67) 
iex> product = %Product{}
 %Pento....
              
            
            
          
              New
 
          
                Dear Sophie. 
I tried to do the “Authorization” exercise and have two questions: 
When trying to plug in an email-service, I found the ...
              
            
            
          
              New
 
          
                “The ProductLive.Index template calls a helper function, live_component/3, that in turn calls on the modal component. ” 
Excerpt From: Br...
              
            
            
          
              New
 
          
                I’m under the impression that when the reader gets to page 136 (“View Data with the Database Inspector”), the code SHOULD be able to buil...
              
            
            
          
              New
 
          
                Hi, I have just acquired Michael Fazio’s “Kotlin and Android Development” to learn about game programming for Android. I have a game in p...
              
            
            
          
              New
 
          
                The allprojects block listed on page 245 produces the following error when syncing gradle: 
“org.gradle.api.GradleScriptException: A prob...
              
            
            
          
              New
 
          
                Hello faithful readers!  If you have tried to follow along in the book, you are asked to start up the dev environment via dx/build and ar...
              
            
            
          
              New
Other popular topics
                         
                      
                       
          
                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
 
          
                I’ve been hearing quite a lot of comments relating to the sound of a keyboard, with one of the most desirable of these called ‘thock’, he...
              
            
            
          
              New
 
          
                Continuing the discussion from Thinking about learning Crystal, let’s discuss - I was wondering which languages don’t GC - maybe we can c...
              
            
            
          
              New
 
          
                Biggest jackpot ever apparently! :upside_down_face: 
I don’t (usually) gamble/play the lottery, but working on a program to predict the...
              
            
            
          
              New
 
          
                A few weeks ago I started using Warp a terminal written in rust. Though in it’s current state of development there are a few caveats (tab...
              
            
            
          
              New
 
          
                Was just curious to see if any were around, found this one: 
I got 51/100: 
  
Not sure if it was meant to buy I am sure at times the b...
              
            
            
          
              New
 
          
                Author Spotlight: 
Peter Ullrich 
@PJUllrich 
Data is at the core of every business, but it is useless if nobody can access and analyze ...
              
            
            
          
              New
 
          
                This is cool! 
DEEPSEEK-V3 ON M4 MAC: BLAZING FAST INFERENCE ON APPLE SILICON
We just witnessed something incredible: the largest open-s...
              
            
            
          
              New
 
          
                Curious what kind of results others are getting, I think actually prefer the 7B model to the 32B model, not only is it faster but the qua...
              
            
            
          
              New
 
          
                A concise guide to MySQL 9 database administration, covering fundamental concepts, techniques, and best practices.
  
Neil Smyth
MySQL...
              
            
            
              
          
              New
Categories:
Sub Categories:
Popular Portals
- /elixir
- /rust
- /ruby
- /wasm
- /erlang
- /phoenix
- /keyboards
- /python
- /rails
- /js
- /security
- /go
- /swift
- /vim
- /clojure
- /emacs
- /haskell
- /java
- /svelte
- /onivim
- /typescript
- /kotlin
- /crystal
- /c-plus-plus
- /tailwind
- /react
- /gleam
- /ocaml
- /elm
- /flutter
- /vscode
- /ash
- /opensuse
- /html
- /centos
- /php
- /deepseek
- /zig
- /scala
- /lisp
- /sublime-text
- /textmate
- /react-native
- /nixos
- /debian
- /agda
- /kubuntu
- /arch-linux
- /django
- /revery
- /ubuntu
- /deno
- /spring
- /nodejs
- /manjaro
- /diversity
- /lua
- /julia
- /c
- /slackware
 
    





