Back to feed
Renewal·서른의 생활코딩

TDD Practice in Spring Boot - Ch.5. Franc-ly Speaking

NS
normalstory
cover image

STS 4.0.1 (Spring Boot): 

Practicing TDD (Test Driven Development) 

 

Opening noteMost people can make the most of their potential by following these two simple rules:

1. Before writing any code, write a failing automated test.

2. Remove duplication.


  Requirements and improvement list

       - $5 + 10CHF = $10 (if the exchange rate is 2:1)

       - $5 x 2 = $10 

- Make amount private           

- Dollar side effects?  

- Money rounding? 

-  equals( )     Implement the equality feature  

- hashCode( ) 

- Equal null

- Equal object

       - New : 5CHF X 2 = 10CHF         <- Goal for this example 

  Purpose. Understanding the rhythm of TDD

1. Quickly add a single test.

2. Run all tests and confirm the new one fails.

3. Make a small change to the code.

4. Run all tests and confirm they all pass.

5. Refactor to remove duplication.



Chapter 5. Franc-ly Speaking 

Ah, the original title is "Franc-ly Speaking." The example in this chapter will walk through converting to francs (CHF).


5-0. PREVIOUS previously 

The last two examples (Ch.3, Ch.4) ended up feeling like I'd implemented the Singleton design pattern. 

For reference, what was made private (instance variable) in Ch.4 is actually discouraged in Spring, which uses Singletons as a Singleton Registry rather than as the design pattern. For details, see Following Toby's Spring 3.1 in Spring Boot: Ch.1 - 1.6 Singleton Registry and Object Scope


5-1. Laying the bridgehead for the first requirement ($5 + 10CHF = $10

First, we'll need an object like Dollar that represents the French currency unit. I copy-pasted the object and its methods and tweaked only the parts that needed changing. The author notes that the reason copy-paste works here is thanks to having simplified (refactored) the tests. 



package com.noramlstory;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestTdd201902 {

	// 5장. 솔직하게 말하면  + Dollar 구문을 복붙했다. 앞서 수행한 리팩토링 덕이다.
	@Test
	public void testFranceMultiplication() {
		Franc five = new Franc(5);
		
		assertEquals(new Franc(10), five.times(2));  
		assertEquals(new Franc(15), five.times(3)); 
	}
	
	// 4장. 프라이버시  
	@Test
	public void testMultiplication() {
		Dollar five = new Dollar(5);

		assertEquals(new Dollar(10), five.times(2));
		assertEquals(new Dollar(15), five.times(3));  
	}
	
	// 3장. 모두를 위한 평등 
	@Test	
	public void testEquality() {
		assertTrue(new Dollar(5).equals(new Dollar(5)));  
		assertFalse(new Dollar(5).equals(new Dollar(6)));
	}
	
}


class Franc{
	private int amount;
	
	Franc(int amount){
		this.amount = amount;
	}
	
	Franc times(int multiplier) {
		return new Franc(amount * multiplier);
	}

	public boolean equals(Object object) {
		Franc franc = (Franc) object;
		return amount == franc.amount;
	}
}

class Dollar{
	private int amount;
	
	Dollar(int amount){
		this.amount = amount;
	}
	
	Dollar times(int multiplier) {
		return new Dollar(amount * multiplier);
	}

	public boolean equals(Object object) {
		Dollar dollar = (Dollar) object;
		return amount == dollar.amount;
	}
}

And the result. Of course~ green light. ;D

But looking at the code, you can almost feel it intuitively — this example is going to introduce more requirements.

Thanks to keeping the code simple, I was able to compile fast and pass the test fast, but new duplications have appeared. 

So again, 

'Before 'solving the first requirement ($5 + 10CHF = $10)' ', the author says we should first go and remove the duplication. 


5-3. Wrap-up 

1) Before attacking the big test ('solving the first requirement ($5 + 10CHF = $10)' ), I made a smaller test.

2) I shamelessly used copy-paste to get the test green quickly, but duplication appeared. 

(1) The author separated the process of creating the testFranceMultiplication(){...} method and

(2) the process of creating the matching class Franc{...} model class. For me it happened so fast I just did both at once. 

3) He declared he wouldn't go home until duplication was gone. Doesn't apply to me ;> 

This English version was translated by Claude.

친절한 찰쓰씨
Written by
친절한 찰쓰씨

Pleasant Charles — UI/UX researcher at AIT. Keeping notes on design, planning, and slow days here since 2010.

More on the author's page

Keep reading

Renewal

Steadily, for the long haul, without burning out

Mar 31, 2026·9 min
Renewal

Tech-life balance

Feb 7, 2026·3 min
Renewal

Humanality, by Park Jeong-ryeol

Feb 7, 2026·11 min