Allra test writing
Skill ComeOnOliver/skillshub/skills/aiskillstore/marketplace/allra-fintech/allra-test-writing
ð§ The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.
npx -y skills add ComeOnOliver/skillshub --skill allra-test-writingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Allra ë°±ìë í ì€íž ìì± íì€. Use when writing test code, choosing test helpers, generating test data with Fixture Monkey, or verifying test coverage.
SKILL.md
23.5 KB, ~6.6k tokens by cl100k_base, as published. Nobody here has run it
Allra Test Writing Standards
Allra ë°±ìë íì í ì€íž ìì± íì€ì ì ìí©ëë€. í ì€íž í¬íŒ ì í, Fixture Monkey ë°ìŽí° ìì±, Given-When-Then íšíŽ, AssertJ ê²ìŠì í¬íší©ëë€.
íë¡ì íž êž°ë³ž ì 볎
ìŽ ê°ìŽëë ë€ì í겜ì êž°ì€ìŒë¡ ìì±ëììµëë€:
- Java: 17 ìŽì
- Spring Boot: 3.2 ìŽì
- Testing Framework: JUnit 5
- Assertion Library: AssertJ
- Mocking: Mockito
- Test Data: Fixture Monkey (ì í ì¬í)
- Container: Testcontainers (ì í ì¬í)
ì°žê³ : íë¡ì ížë³ë¡ ì¬ì©íë ëŒìŽëžë¬ëЬë ë²ì ìŽ ë€ë¥Œ ì ììµëë€. íë¡ì ížì ë§ê² ì¡°ì íì¬ ì¬ì©íìžì.
í ì€íž í¬íŒ ì í ê°ìŽë
죌ì: ìë í
ì€íž í¬íŒë Allra íì€ í
í늿ìì ì ê³µë©ëë€. íë¡ì ížì ìŽë¬í í¬íŒê° ìë 겜ì°, Spring Boot Ʞ볞 í
ì€íž ìŽë
ží
ìŽì
(@SpringBootTest, @DataJpaTest, @WebMvcTest ë±)ì ì§ì ì¬ì©íë, ìŽ ê°ìŽëì í
ì€íž íšíŽê³Œ ìì¹ì ëìŒíê² ì ì©í©ëë€.
| í¬íŒ | íê·ž | ì©ë | ë¬Žê² | ìžì ? |
|---|---|---|---|---|
| IntegrationTest | Integration | ì¬ë¬ ìë¹ì€ íµí© | ðŽ ë¬Žê±°ì | ì 첎 ìí¬íë¡ì° |
| RdbTest | RDB | Repository, QueryDSL | ð¡ ì€ê° | 쿌늬 ê²ìŠ |
| ControllerTest | Controller | API ìëí¬ìžíž | ð¢ ê°ë²Œì | REST API ê²ìŠ |
| RedisTest | Redis | Redis ìºì± | ð¢ ê°ë²Œì | ìºì ê²ìŠ |
| MockingUnitTest | MockingUnit | Service ëšì | ð¢ ë§€ì° ê°ë²Œì | ë¹ìŠëì€ ë¡ì§ |
| PojoUnitTest | PojoUnit | ëë©ìž ë¡ì§ | ð¢ ë§€ì° ê°ë²Œì | ìì ìë° |
ì í íë¡ì°
API ìëí¬ìžíž? â ControllerTest
ì¬ë¬ ìë¹ì€ íµí©? â IntegrationTest
Repository/QueryDSL? â RdbTest
Redis ìºì±? â RedisTest
Service ë¡ì§ (Mock)? â MockingUnitTest
ëë©ìž ë¡ì§ (POJO)? â PojoUnitTest
ð¯ Mock vs Integration ì í êž°ì€ (ì€ì!)
ìì¹: Ʞ볞ì MockingUnitTest, êŒ íìí ëë§ IntegrationTest
목í: IntegrationTest ë¹ìš 5% ìŽí ì ì§
ìì¬ê²°ì íë¡ì°ì°šíž
âââââââââââââââââââââââââââââââââââ
â 묎ìì í
ì€ížíë €ê³ íëê°? â
ââââââââââââââ¬âââââââââââââââââââââ
â
ââââââââââŒâââââââââ
â ëë©ìž ë¡ì§ë§? â ââYesââ> PojoUnitTest
ââââââââââ¬âââââââââ
â No
ââââââââââŒââââââââââââââââââââââ
â Repository/QueryDSL 쿌늬? â ââYesââ> RdbTest
ââââââââââ¬ââââââââââââââââââââââ
â No
ââââââââââŒââââââââââââââââââââââ
â API ìëí¬ìžíž ìëµ/ê²ìŠ? â ââYesââ> ControllerTest
ââââââââââ¬ââââââââââââââââââââââ
â No
ââââââââââŒââââââââââââââââââââââââââââââ
â Service ë¹ìŠëì€ ë¡ì§ ê²ìŠ? â
ââââââââââ¬ââââââââââââââââââââââââââââââ
â
ââââââââââŒâââââââââââââââââââââââââââââââââââââââââââ
â ë€ì ì€ íëëŒë íŽë¹íëê°? â
â â
â 1. ð° êžì ì²ëЬ (ì
êž/ì¶êž/ìŽì²Ž/íë¶) â
â 2. ð ížëìì
ë¡€ë°±ìŽ ì€ìí ìí¬íë¡ì° â
â 3. ð ì¬ë¬ í
ìŽëž ë°ìŽí° ì í©ì± ê²ìŠ â
â 4. ð ì€ì DB ì ìœì¡°ê±Ž ê²ìŠ íì â
â 5. ð ë³µì¡í ìí ì ìŽ (3ëšê³ ìŽì) â
â 6. ð¯ ìŽë²€íž ë°í/늬ì€ë íµí© ê²ìŠ â
â 7. ð€ 3ê° ìŽì ìë¹ì€ íì íë ¥ â
ââââââ¬âââââââââââââââââââââââââââââââââââââââ¬âââââââââ
â Yes â No
â â
ââââââŒâââââââââââââ âââââââââââŒâââââââââââ
â IntegrationTest â â MockingUnitTest â
â (ìµìí) â â (Ʞ볞 ì í) â
âââââââââââââââââââ ââââââââââââââââââââââ
IntegrationTestê° íìí 구첎ì ìž ìŒìŽì€
â 1. êžì ì²ëЬ (ì êž/ì¶êž/ìŽì²Ž/íë¶)
ìŽì : ëìŽ êŽë šë ë¡ì§ì ì€ì DB ížëìì ëì ê²ìŠ íì
// ìì: íë© ì ì² (FsData â FsPayment â PointUsage â UserAccount ì°ê³)
@DisplayName("íë© ì ì² ì êžì¡ ì°šê° ë° ê²°ì ìì±")
class ApplyServiceIntegrationTest extends IntegrationTest {
@Test
@Transactional
void apply_DecreasesAmount_Success() {
// given: ì¬ì©ì ìì¡ 100ë§ì
User user = createUserWithBalance(1_000_000);
// when: 50ë§ì íë© ì ì²
applyService.apply(new ApplyRequest(user.getId(), 500_000));
// then: ì€ì DBìì ìì¡ 50ë§ì íìž
User updated = userRepository.findById(user.getId()).get();
assertThat(updated.getBalance()).isEqualTo(500_000);
// then: FsPayment ìì± íìž
FsPayment payment = fsPaymentRepository.findByUserId(user.getId()).get();
assertThat(payment.getAmount()).isEqualTo(500_000);
}
}
â 2. ížëìì ë¡€ë°±ìŽ ì€ìí ìí¬íë¡ì°
ìŽì : ì€íš ì 몚ë ìì ìŽ ììì ìŒë¡ 례백ëìŽìŒ íš
// ìì: ê²°ì ì€íš ì ì 첎 례백
@Test
@DisplayName("ê²°ì ì€íš ì ì ì² ë°ìŽí°ë 례백")
void apply_PaymentFails_RollbackAll() {
// given
User user = createUser();
mockPaymentGateway_ToFail(); // ìžë¶ ê²°ì ë MockìŒë¡
// when & then
assertThatThrownBy(() -> applyService.apply(request))
.isInstanceOf(PaymentException.class);
// then: DBì ìŽë€ ë°ìŽí°ë ì ì¥ëì§ ìì
assertThat(fsDataRepository.findAll()).isEmpty();
assertThat(fsPaymentRepository.findAll()).isEmpty();
}
ì°žê³ : ìžë¶ ì°ë(ê²°ì ê²ìŽížìšìŽ, ìžë¶ API)ì @MockBeanìŒë¡ ì²ëЬ
â 3. ì¬ë¬ í ìŽëž ë°ìŽí° ì í©ì± ê²ìŠ
ìŽì : êŽë šë 몚ë í ìŽëžì ìíê° ìŒêŽëê² ì ì§ëëì§ íìž
// ìì: ê³ìœ ìì± ì UserAccount, Contract, FsData 몚ë ìì±
@Test
@DisplayName("ì ê· ê³ìœ ì êŽë š í
ìŽëž 몚ë ìì±")
void createContract_CreatesAllRelatedData() {
// when
contractService.createContract(userId, contractType);
// then: 3ê° í
ìŽëž 몚ë ë°ìŽí° 졎ì¬
assertThat(userAccountRepository.findByUserId(userId)).isPresent();
assertThat(contractRepository.findByUserId(userId)).isPresent();
assertThat(fsDataRepository.findByUserId(userId)).isPresent();
}
â 4. ì€ì DB ì ìœì¡°ê±Ž ê²ìŠ
ìŽì : Unique, FK, Check ì ìœì¡°ê±Žì ì€ì DBììë§ íìž ê°ë¥
// ìì: ì€ë³µ ê³ì¢ ë±ë¡ ë°©ì§
@Test
@DisplayName("ëìŒ ê³ì¢ë²íž ì€ë³µ ë±ë¡ ì ììž")
void registerAccount_Duplicate_ThrowsException() {
// given
userAccountRepository.save(new UserAccount(userId, "123-456-789"));
// when & then: Unique ì ìœì¡°ê±Ž ìë°
assertThatThrownBy(() ->
userAccountRepository.save(new UserAccount(userId, "123-456-789"))
).isInstanceOf(DataIntegrityViolationException.class);
}
â 5. ë³µì¡í ìí ì ìŽ (3ëšê³ ìŽì)
ìŽì : ìí ë³í íëŠì ì€ì ìë늬ì€ëë¡ ê²ìŠ
// ìì: ê³ìœ ìí ì ìŽ (ì ì² â ì¬ì¬ â ì¹ìž â ìë£)
@Test
@DisplayName("ê³ìœ ìí¬íë¡ì° ì 첎 ê²ìŠ")
void contractWorkflow_FullCycle() {
// given: ì ì²
Contract contract = contractService.create(userId);
assertThat(contract.getStatus()).isEqualTo(ContractStatus.PENDING);
// when: ì¬ì¬
contractService.review(contract.getId());
// then
Contract reviewed = contractRepository.findById(contract.getId()).get();
assertThat(reviewed.getStatus()).isEqualTo(ContractStatus.REVIEWED);
// when: ì¹ìž
contractService.approve(contract.getId());
// then
Contract approved = contractRepository.findById(contract.getId()).get();
assertThat(approved.getStatus()).isEqualTo(ContractStatus.APPROVED);
}
â 6. ìŽë²€íž ë°í/늬ì€ë íµí© ê²ìŠ
ìŽì : ìŽë²€ížê° ì€ì ë¡ ë°íëê³ ëŠ¬ì€ëê° ëìíëì§ íìž
// ìì: ê³ìœ ìë£ ìŽë²€íž â ì늌 ë°ì¡
@Test
@DisplayName("ê³ìœ ìë£ ì ì늌 ìŽë²€íž ë°í")
void completeContract_PublishesEvent() {
// given
Contract contract = createContract(userId);
// when
contractService.complete(contract.getId());
// then: ì€ì ë¡ ìëŠŒìŽ ë°ì¡ëìëê°? (ìžë¶ ì늌ì @MockBean)
verify(notificationService).sendContractCompleteNotification(userId);
}
â 7. 3ê° ìŽì ìë¹ì€ê° íìì ìŒë¡ íë ¥
ìŽì : ìë¹ì€ ê° ìížìì©ì ì€ì í겜ìì ê²ìŠ
// ìì: 죌묞 ìì± â ì¬ê³ ì°šê° â ê²°ì â ì늌
@Test
@DisplayName("죌묞 ìì± ìí¬íë¡ì°")
void createOrder_FullWorkflow() {
// given
Product product = createProductWithStock(100);
// when
orderService.createOrder(userId, product.getId(), 10);
// then: ì¬ê³ ì°šê°
Product updated = productRepository.findById(product.getId()).get();
assertThat(updated.getStock()).isEqualTo(90);
// then: ê²°ì ìì±
Payment payment = paymentRepository.findByUserId(userId).get();
assertThat(payment.getStatus()).isEqualTo(PaymentStatus.COMPLETED);
}
MockingUnitTestë¡ ì¶©ë¶í ìŒìŽì€
â ëë¶ë¶ì Service ë¡ì§
- ëšì ì¡°í (findById, findAll)
- ë°ìŽí° ë³í/ê³ì°
- ê²ìŠ ë¡ì§ (validation)
- ëšìŒ ìí°í° CRUD
- ë¹ìŠëì€ ê·ì¹ ê²ìŠ
// ìì: í ìžìš ê³ì° ë¡ì§ (MockìŒë¡ ì¶©ë¶)
@ExtendWith(MockitoExtension.class)
class DiscountServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private DiscountService discountService;
@Test
@DisplayName("VIP íì 10% í ìž ê³ì°")
void calculateDiscount_VipUser_10Percent() {
// given
User vipUser = User.builder().grade("VIP").build();
when(userRepository.findById(1L)).thenReturn(Optional.of(vipUser));
// when
BigDecimal discount = discountService.calculateDiscount(1L, new BigDecimal("10000"));
// then
assertThat(discount).isEqualByComparingTo(new BigDecimal("1000"));
}
}
ìžë¶ ì°ë ì²ëЬ ìì¹
ì€ì: IntegrationTestììë ìžë¶ ìì€í
ì @MockBeanìŒë¡ ì²ëЬ
@SpringBootTest
class PaymentServiceIntegrationTest extends IntegrationTest {
@Autowired
private PaymentService paymentService;
@MockBean // ìžë¶ ê²°ì ê²ìŽížìšìŽë Mock
private ExternalPaymentGateway externalPaymentGateway;
@MockBean // ìžë¶ ì늌 ìë¹ì€ë Mock
private ExternalNotificationService notificationService;
@Test
@DisplayName("ê²°ì ì±ê³µ ì ëŽë¶ ë°ìŽí° ì í©ì± ê²ìŠ")
void processPayment_Success() {
// given: ìžë¶ ê²°ì ë ì±ê³µìŒë¡ Mock
when(externalPaymentGateway.charge(any()))
.thenReturn(new PaymentResult("SUCCESS", "tx-123"));
// when: ì€ì ëŽë¶ ë¡ì§ ê²ìŠ
paymentService.processPayment(userId, amount);
// then: ëŽë¶ DB ìí íìž
Payment payment = paymentRepository.findByUserId(userId).get();
assertThat(payment.getStatus()).isEqualTo(PaymentStatus.COMPLETED);
assertThat(payment.getExternalTxId()).isEqualTo("tx-123");
}
}
í ì€íž ì ëµ ììœ
| í ì€íž ì í | 목í ë¹ìš | ì€í ìë | 죌ì ì¬ì©ì² |
|---|---|---|---|
| PojoUnitTest | 30% | â¡ïž 0.01ìŽ | ëë©ìž ë¡ì§, ì ížëŠ¬í° |
| MockingUnitTest | 50% | â¡ïž 0.1ìŽ | Service ë¹ìŠëì€ ë¡ì§ |
| ControllerTest | 10% | ð¡ 0.5ìŽ | API ê²ìŠ |
| RdbTest | 5% | ð¡ 1ìŽ | ë³µì¡í 쿌늬 ê²ìŠ |
| IntegrationTest | 5% | ðŽ 5ìŽ | êžì /ížëìì /ìí¬íë¡ì° |
ë¹ ë¥ž íëš ì²Ží¬ëЬì€íž
ìë¡ìŽ í ì€ížë¥Œ ìì±í ë ë€ìì íìžíìžì:
â¡ ëìŽ êŽë šëìŽ ìëì? (ì
êž/ì¶êž/ê²°ì )
â Yes: IntegrationTest
â¡ ì€íš ì ë°ìŽí° ë¡€ë°±ìŽ ì€ìíê°ì?
â Yes: IntegrationTest
â¡ 3ê° ìŽì í
ìŽëžì ì í©ì±ì íìžíŽìŒ íëì?
â Yes: IntegrationTest
â¡ DB ì ìœì¡°ê±Ž(Unique/FK)ìŽ íµì¬ìžê°ì?
â Yes: IntegrationTest
â¡ ë³µì¡í ìí ì ìŽ(3ëšê³+)륌 ê²ìŠíëì?
â Yes: IntegrationTest
â¡ ìŽë²€íž ë°í/늬ì€ë륌 ê²ìŠíëì?
â Yes: IntegrationTest
â¡ 3ê° ìŽì ìë¹ì€ê° íë ¥íëì?
â Yes: IntegrationTest
몚ë No â MockingUnitTest ì¬ì©
í ì€íž í¬íŒ 구조
IntegrationTest - íµí© í ì€íž
@Tag("Integration")
@SpringBootTest
public abstract class IntegrationTest {
// ì 첎 Spring Context, Testcontainers íì©
}
ìžì : ì¬ë¬ ìë¹ì€ íë ¥, ì€ì DB/ìžë¶ ìì€í
íì
죌ì: ê°ì¥ 묎거ì, ìžë¶ APIë @MockBean ì¬ì©
RdbTest - Repository í ì€íž
@Tag("RDB")
@DataJpaTest
public abstract class RdbTest {}
ìžì : Repository CRUD, QueryDSL 쿌늬, N+1 묞ì ê²ìŠ
ControllerTest - API í ì€íž
@Tag("Controller")
@WebMvcTest(TargetController.class)
public abstract class ControllerTest {
@Autowired
protected MockMvc mockMvc;
}
ìžì : API ìëí¬ìžíž, HTTP Status, ì
ë ¥ ê²ìŠ
죌ì: Serviceë @MockBean íì
RedisTest - Redis í ì€íž
@Tag("Redis")
@DataRedisTest
public abstract class RedisTest {}
ìžì : Redis ìºì±, ìžì ì ì¥ì ê²ìŠ
MockingUnitTest - Service ëšì í ì€íž
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
}
ìžì : Service ë¡ì§ ëšì í
ì€íž, ë¹ ë¥ž í
ì€íž
죌ì: Spring Context ìì, @Autowired ë¶ê°
PojoUnitTest - ëë©ìž ë¡ì§ í ì€íž
class UserTest {
@Test
void activate_Success() {
// ìì ìë° ë¡ì§ í
ì€íž
}
}
ìžì : ëë©ìž ìí°í°, VO, ì ížëŠ¬í° íŽëì€
Fixture Monkey - í ì€íž ë°ìŽí° ìì±
ìì¡Žì± ì€ì
// Gradle
testImplementation 'com.navercorp.fixturemonkey:fixture-monkey-starter:1.0.13'
<!-- Maven -->
<dependency>
<groupId>com.navercorp.fixturemonkey</groupId>
<artifactId>fixture-monkey-starter</artifactId>
<version>1.0.13</version>
<scope>test</scope>
</dependency>
ì¬ì©ë²
import static {your.package}.fixture.FixtureFactory.FIXTURE_MONKEY;
// ëšì ìì±
User user = FIXTURE_MONKEY.giveMeOne(User.class);
// í¹ì íë ì§ì
User user = FIXTURE_MONKEY.giveMeBuilder(User.class)
.set("email", "[email protected]")
.set("active", true)
.sample();
// ì¬ë¬ ê° ìì±
List<User> users = FIXTURE_MONKEY.giveMe(User.class, 10);
Given-When-Then íšíŽ (íì)
몚ë í ì€ížë Given-When-Then íšíŽ íì
@Test
@DisplayName("ì¬ì©ì ìì± - ì±ê³µ")
void createUser_Success() {
// given - í
ì€íž ì€ë¹
UserRequest request = new UserRequest("[email protected]", "password");
User savedUser = FIXTURE_MONKEY.giveMeOne(User.class);
when(userRepository.save(any())).thenReturn(savedUser);
// when - ì€ì ì€í
UserResponse response = userService.createUser(request);
// then - ê²ìŠ
assertThat(response).isNotNull();
verify(userRepository, times(1)).save(any());
}
AssertJ ê²ìŠ íšíŽ
// ëšìŒ ê°
assertThat(response).isNotNull();
assertThat(response.userId()).isEqualTo(1L);
// 컬ë ì
assertThat(users).hasSize(3);
assertThat(users).extracting(User::getEmail)
.containsExactlyInAnyOrder("[email protected]", "[email protected]");
// Boolean
assertThat(user.isActive()).isTrue();
// ììž
assertThatThrownBy(() -> userService.findById(999L))
.isInstanceOf(BusinessException.class)
.hasMessageContaining("USER_NOT_FOUND");
// Optional
assertThat(result).isPresent();
assertThat(result.get().getName()).isEqualTo("íêžžë");
Mockito íšíŽ
Mock ì€ì
// ë°íê°
when(userRepository.findById(1L)).thenReturn(Optional.of(user));
// void ë©ìë
doNothing().when(emailService).sendEmail(any());
// ììž ë°ì
when(userRepository.findById(999L))
.thenThrow(new BusinessException(ErrorCode.USER_NOT_FOUND));
Mock ížì¶ ê²ìŠ
// ížì¶ íì
verify(userRepository, times(1)).findById(1L);
verify(userRepository, never()).delete(any());
// ìžì ê²ìŠ
verify(userRepository).save(argThat(user ->
user.getEmail().equals("[email protected]")
));
í ì€íž ëª ëª ê·ì¹
íŽëì€
class ApplyServiceIntegrationTest extends IntegrationTest // Integration
class UserRepositoryTest extends RdbTest // Repository
class UserControllerTest extends ControllerTest // Controller
class UserServiceTest // Service Unit
class UserTest // Domain
ë©ìë
// íšíŽ: {ë©ìëëª
}_{ìë늬ì€}_{ìì결곌}
@Test
@DisplayName("ì¬ì©ì ìì± - ì±ê³µ")
void createUser_ValidRequest_Success()
@Test
@DisplayName("ì¬ì©ì ì¡°í - ì¬ì©ì ìì")
void findById_UserNotFound_ThrowsException()
í ì€íž ìì
Controller í ì€íž
@DisplayName("User -> UserController í
ì€íž")
@WebMvcTest(UserController.class)
class UserControllerTest extends ControllerTest {
@MockBean
private UserService userService;
@Test
@DisplayName("ì¬ì©ì ì¡°í API - ì±ê³µ")
void getUser_Success() throws Exception {
// given
Long userId = 1L;
UserResponse response = new UserResponse(userId, "[email protected]");
when(userService.findById(userId)).thenReturn(response);
// when & then
mockMvc.perform(get("/api/v1/users/{id}", userId))
.andExpect(status().isOk())
.andExpect(jsonPath("$.userId").value(userId));
}
}
Service ëšì í ì€íž
@ExtendWith(MockitoExtension.class)
@DisplayName("User -> UserService ëšì í
ì€íž")
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
@DisplayName("ì¬ì©ì ì¡°í - ì±ê³µ")
void findById_Success() {
// given
Long userId = 1L;
User user = FIXTURE_MONKEY.giveMeBuilder(User.class)
.set("id", userId)
.sample();
when(userRepository.findById(userId)).thenReturn(Optional.of(user));
// when
UserResponse response = userService.findById(userId);
// then
assertThat(response).isNotNull();
assertThat(response.userId()).isEqualTo(userId);
verify(userRepository, times(1)).findById(userId);
}
}
Repository í ì€íž
@DisplayName("User -> UserRepository í
ì€íž")
class UserRepositoryTest extends RdbTest {
@Autowired
private UserRepository userRepository;
@Test
@DisplayName("íì± ì¬ì©ì ì¡°í - ì±ê³µ")
void findActiveUsers_Success() {
// given
User active = FIXTURE_MONKEY.giveMeBuilder(User.class)
.set("active", true)
.sample();
userRepository.save(active);
// when
List<UserDto> result = userRepository.findActiveUsers();
// then
assertThat(result).hasSize(1);
assertThat(result).extracting(UserDto::email)
.contains(active.getEmail());
}
}
When to Use This Skill
ìŽ skillì ë€ì ìí©ìì ìëìŒë¡ ì ì©ë©ëë€:
- í ì€íž íìŒ ìì± ëë ìì
- í ì€íž í¬íŒ ì í (IntegrationTest vs MockingUnitTest íëš)
- í ì€íž ë°ìŽí° ìì± (Fixture Monkey ì¬ì©)
- Given-When-Then íšíŽ ì ì©
- AssertJ ê²ìŠ ìœë ìì±
- Mockito Mock ì€ì ë° ê²ìŠ
í¹í ì€ì: ìë¡ìŽ Service í ì€íž ìì± ì 뚌ì "Mock vs Integration ì í êž°ì€"ì íìžíìžì!
Checklist
í ì€íž ìœë ìì± ì íìžì¬í:
몚ë í ì€íž ê³µíµ
- Given-When-Then íšíŽì ë°ë¥Žëê°?
- @DisplayNameìŒë¡ í ì€íž ìëê° ëª ííê°?
- AssertJë¡ ê²ìŠíëê°?
- ë©ìëëª
ìŽ
ë©ìë_ìë늬ì€_결곌íšíŽìžê°?
í ì€íž í¬íŒ ì í (ê°ì¥ 뚌ì íìž!)
- êžì ì²ëЬ(ì êž/ì¶êž/ê²°ì ) ëë ížëìì 례백 ê²ìŠìŽ íìíê°? â IntegrationTest
- 3ê° ìŽì í ìŽëž ì í©ì± ëë DB ì ìœì¡°ê±Ž ê²ìŠìŽ íìíê°? â IntegrationTest
- ë³µì¡í ìí ì ìŽ(3ëšê³+) ëë ìŽë²€íž ë°í/늬ì€ë ê²ìŠìŽ íìíê°? â IntegrationTest
- 3ê° ìŽì ìë¹ì€ê° íë ¥íëê°? â IntegrationTest
- ì 조걎 몚ë íŽë¹ ìëš â MockingUnitTest ì¬ì©
IntegrationTest
- ì ì í êž°ì€ ì€ íë ìŽìì íŽë¹íëê°?
- ìžë¶ APIë @MockBeanìŒë¡ ì²ëЬíëê°?
- ì ë§ IntegrationTestê° íìíì§ ë€ì íë² ê²í íëê°?
RdbTest
- Repository/QueryDSL í ì€ížë§ í¬íšíëê°?
- N+1 묞ì 륌 ê²ìŠíëê°?
ControllerTest
- @WebMvcTest(TargetController.class)륌 ëª ìíëê°?
- Serviceë @MockBeanìŒë¡ ì²ëЬíëê°?
- HTTP Status Code륌 ê²ìŠíëê°?
MockingUnitTest
- @MockìŒë¡ ì졎ì±, @InjectMocksë¡ í ì€íž ëìì 죌ì íëê°?
- verify()ë¡ Mock ížì¶ì ê²ìŠíëê°?
PojoUnitTest
- ëë©ìž ë¡ì§ë§ í ì€ížíëê°?
- ìžë¶ ì졎ì±ìŽ ìëê°?
í ì€íž ì€í ëª ë ¹ìŽ
Gradle
./gradlew test # ì 첎 í
ì€íž
./gradlew test --tests * -Dtest.tags=Integration # íê·žë³ ì€í
./gradlew test --tests UserServiceTest # í¹ì íŽëì€
Maven
./mvnw test # ì 첎 í
ì€íž
./mvnw test -Dgroups=Integration # íê·žë³ ì€í
./mvnw test -Dtest=UserServiceTest # í¹ì íŽëì€
í ì€íž íì§ êž°ì€
- 컀ë²ëЬì§: íµì¬ ë¹ìŠëì€ ë¡ì§ 70% ìŽì
- 격늬ì±: ê° í ì€ížê° ë 늜ì ìŒë¡ ì€í ê°ë¥
- ìë: ëšì í ì€íž 1ìŽ ìŽëŽ, íµí© í ì€íž 5ìŽ ìŽëŽ
- ëª íì±: í ì€íž ìŽëŠë§ìŒë¡ ìë íì ê°ë¥
- ì 뢰ì±: ê°ì ì ë ¥ì íì ê°ì 결곌
What ships with it
17.6 KB alongside SKILL.md
GitHub clipped this repositoryâs file list, so this is at least 1 file and may be more.
- skill-report.json17.6 KB