๐น TDD์ ๋ํ์ฌ
์ฝ๋ ํ์ง ํฅ์
์ ์ง๋ณด์์ฑ ๊ฐํ
๋ช ํํ ์ค๊ณ ์ ๋
๊ฐ๋ฐ์ ๊ฐ ํ์ ๊ฐํ
์ ์ฉ์ด ์ ํฉํ ์ํฉ
์ ์ฉ์ด ์ด๋ ค์ด ์ํฉ
ํ ์คํธ์ ๋ฒ์ ์กฐ์
์ฐ์ ์์๋ฅผ ์ ํ๋ผ
์๋ํ์ ๋ณํํ๋ผ
ํ ์คํธ๋ฅผ ๋ฌธ์๋ก ํ์ฉํ๋ผ
JUnit 5๋ ๋จ์ ํ ์คํธ(Unit Test)๋ฅผ ์์ฑํ๊ธฐ ์ํ ํต์ฌ ๋๊ตฌ์ ๋๋ค. Spring Boot๋ ๊ธฐ๋ณธ์ ์ผ๋ก JUnit 5๋ฅผ ์ง์ํ๋ฉฐ, ๋ค์ํ ์ ๋ํ ์ด์ ๊ณผ Assertions API๋ฅผ ํตํด ํ ์คํธ๋ฅผ ์ฝ๊ฒ ์์ฑํ ์ ์์ต๋๋ค.
@Test
@BeforeEach
/ @AfterEach
@BeforeAll
/ @AfterAll
@Disabled
@Tag
assertEquals(expected, actual)
: ๋ ๊ฐ์ด ๋์ผํ์ง ๋น๊ต.assertTrue(condition)
: ์กฐ๊ฑด์ด ์ฐธ์ธ์ง ํ์ธ.assertThrows(exception, executable)
: ํน์ ์์ธ๊ฐ ๋ฐ์ํ๋์ง ํ์ธ.import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class CalculatorTest {
@Test
void additionShouldBeCorrect() {
Calculator calculator = new Calculator();
int result = calculator.add(2, 3);
assertEquals(5, result, "2 + 3์ 5์ฌ์ผ ํฉ๋๋ค.");
}
@Test
void divisionShouldThrowExceptionForZero() {
Calculator calculator = new Calculator();
assertThrows(ArithmeticException.class, () -> calculator.divide(5, 0));
}
}
Spring Test Framework๋ Spring Boot ์ ํ๋ฆฌ์ผ์ด์ ์ ํตํฉ ํ ์คํธ๋ฅผ ์ง์ํฉ๋๋ค. ์คํ๋ง ์ปจํ ์คํธ๋ฅผ ๋ก๋ํ์ฌ Spring Bean, ์์กด์ฑ ์ฃผ์ , ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๋ ๋ฑ์ ํ ์คํธํ ์ ์์ต๋๋ค.
@SpringBootTest
@SpringBootTest
class MyAppTests {
@Test
void contextLoads() {
}
}
@WebMvcTest
@WebMvcTest(controllers = MyController.class)
class MyControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void shouldReturnDefaultMessage() throws Exception {
mockMvc.perform(get("/api/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello, World!"));
}
}
@DataJpaTest
@DataJpaTest
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void shouldSaveAndFindUser() {
User user = new User("John Doe", "john@example.com");
userRepository.save(user);
Optional<User> result = userRepository.findByEmail("john@example.com");
assertTrue(result.isPresent());
assertEquals("John Doe", result.get().getName());
}
}
4.@MockBean
@SpringBootTest
class MyServiceTest {
@MockBean
private MyRepository myRepository;
@Autowired
private MyService myService;
@Test
void shouldUseMockedRepository() {
when(myRepository.findSomething()).thenReturn("Mocked Result");
String result = myService.getSomething();
assertEquals("Mocked Result", result);
}
}
JDBC ๋๋ผ์ด๋ฒ ์ค๋น
lib
๋๋ ํ ๋ฆฌ์ ๋ณต์ฌ.
mysql-connector-java
, PostgreSQL์ postgresql.jar
.ํ ์คํธ ๋์ ์ ํ๋ฆฌ์ผ์ด์ ์ค๋น
DBConnection
).jdbc:mysql://localhost:3306/testdb
).com.mysql.cj.jdbc.Driver
).Thread Group์ JDBC Request๋ฅผ ์ถ๊ฐ.
์ค์ :
DBConnection
).Select Statement
: ๋ฐ์ดํฐ ์กฐํ ์ฟผ๋ฆฌ.Update Statement
: ๋ฐ์ดํฐ ์์ ์ฟผ๋ฆฌ.SELECT * FROM users WHERE status = 'ACTIVE';
๋งค๊ฐ๋ณ์๋ฅผ ๋์ ์ผ๋ก ์ค์ ํ๋ ค๋ฉด Prepared Statement๋ฅผ ์ฌ์ฉํ ์ ์์:
SELECT * FROM users WHERE age > ?;
30
(๋์ ์ผ๋ก ์ ๋ฌํ ๊ฐ).Thread Group ์ค์ :
๋ถํ๋ฅผ ๋์ ์ผ๋ก ๋ณ๊ฒฝ:
HTTP ์์ฒญ์ ํตํด JPA ๋ฉ์๋ ํธ์ถ
http://localhost:8080/api/users?status=ACTIVE
JPA ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์ ๋์ ์ค์
age,status
25,ACTIVE 30,INACTIVE 35,ACTIVE
${age}
์ ${status}
๋ก ๋์ฒด.JMeter View Results Tree
Database Monitoring Tools
Spring Actuator Metrics
@Timed
์ ๋ํ
์ด์
๋๋ Actuator ๋ฉํธ๋ฆญ์ ํตํด JPA ๋ฉ์๋์ ์คํ ์๊ฐ ์ธก์ .๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ ์ด๊ธฐํ
์ค์ ํ๊ฒฝ๊ณผ ๋์ผํ ์ค์
์ ์ ๋ถํ ์ค์