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

TDD Practice in Spring Boot - Ch.4. Privacy

NS
normalstory
cover image

STS 4.0.1 (Spring Boot): 

Practicing TDD (Test Driven Development) 

 

Opening noteMost people can bring out their full potential just 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            <- Goal for this example 

- Dollar side effects?  

- Money rounding? 

- New: equals( )    Implement the equality feature  

hashCode( ) 

Equal null

- Equal object

  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 4. Privacy  


4-1.  PREVIOUS previously 

Here's the Dollar.class I've been building up so far. 

class Dollar{
	int amount;
	
	Dollar(int amount){
		this.amount = amount;
	}
	
	Dollar times(int multiplier) {
		return new Dollar(amount * multiplier);
	}
	
	// 3-4 동치성을 일반화 한다 
	public boolean equals(Object object) {
		Dollar dollar = (Dollar) object;
		return amount == dollar.amount;
	}
}

This class holds a variable called amount and has methods that return it: a constructor, times(), and equals(). 


In Chapter 3 we solved equality with the equals() method; this chapter is where we'll make it so times() returns a Dollar whose value is the called-on object's value multiplied by the argument. So far, the test code doesn't really say that precisely. That's what the author says.

I wondered what he meant. Reading all the way through — the results aren't different, but strictly speaking they are.  And within that distinction sits the goal of this chapter. 

If you look at the previous test code, in the process of "times() returning a Dollar whose value is the called-on object's value multiplied by the argument received," the code is passing through a Dollar object called product. In other words, two Dollar objects (the ones underlined above) are being used to carry out that process. 

Let's boil that down to one. 


Once we do, the only code using the Dollar class's instance variable amount is Dollar itself. 

One more thing you might wonder here.. there's five and there's product, so why do we say "itself"? In my viewfive is the object returned through the new operator — it's returning itself. And product is just a variable of type Dollar.


Anyway, since the only code using the instance variable amount is Dollar itself, we can change amount to private. 

A value only the object itself can use.



4-2.  Reflected in the code  

1) Rewrite the assertion side so it uses the equality we built. 

2) Remove "Dollar products;" and related lines, and inline the multiplication into the equality-style assertion. 


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 TestTdd2019 {
	
        // 4장. 프라이버시 
	@Test
	public void testMultiplication() {
		Dollar five = new Dollar(5);
		
		//assertEquals(10, product.amount);

		assertEquals(new Dollar(10), five.times(2));  // assertion 수정 : 동치성을 반영, product 변수 제거 
		
		assertEquals(new Dollar(15), five.times(3));  // assertion 수정 : 동치성을 반영, product 변수 제거 
	}
	
	// 3장. 모두를 위한 평등 
	@Test	
	public void testEquality() {
		// 3-1. 일단 테스트를 진행한다.  $5 == $5    ( $5 같다 $5 )
		assertTrue(new Dollar(5).equals(new Dollar(5)));  
		
		// 3-3. 삼각 측량을 위해 거짓 비교?를 하나 추가 해본다.    $5 != $6	( $5 같지않다 $6 )
		assertFalse(new Dollar(5).equals(new Dollar(6)));
	}
	
}

class Dollar{
	private int amount;
	
	Dollar(int amount){
		this.amount = amount;
	}
	
	Dollar times(int multiplier) {
		return new Dollar(amount * multiplier);
	}
	
	// 3-4 동치성을 일반화 한다 
	public boolean equals(Object object) {
		Dollar dollar = (Dollar) object;
		return amount == dollar.amount;
	}
}


4-3.  Result


4-4.  Reviewing the practice so far 

1) Use newly developed features purely to improve the tests.

2) If two tests fail at the same time, we're in trouble.

It's written that if the equality test fails to verify that the equality code actually works, then the multiplication test will also fail to verify that the multiplication code actually works. To put it another way, 

we rewrote the previously written multiplication test using equality-style code, so if the equality code is wrong, there's no way to tell whether the earlier multiplication code was right or wrong either — that's how I hear it.

3) Press on even with risk factors present.

4) To loosen the coupling between the test and the code, use new features of the object under test. 

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