mirror of
https://github.com/github/awesome-copilot.git
synced 2026-03-20 08:05:12 +00:00
- Introduced MockMvcTester for AssertJ-style assertions in Spring MVC testing. - Added @RestClientTest for testing REST clients with MockRestServiceServer. - Implemented RestTestClient as a modern alternative to TestRestTemplate. - Documented migration steps from Spring Boot 3.x to 4.0, including dependency and annotation changes. - Created an overview of test slices to guide testing strategies. - Included Testcontainers setup for JDBC testing with PostgreSQL and MySQL. - Enhanced @WebMvcTest documentation with examples for various HTTP methods and validation.
4.8 KiB
4.8 KiB
Instancio
Generate complex test objects automatically. Use when entities/DTOs have 3+ properties.
When to Use
- Objects with 3 or more properties
- Setting up test data for repositories
- Creating DTOs for controller tests
- Avoiding repetitive builder/setter calls
Dependency
<dependency>
<groupId>org.instancio</groupId>
<artifactId>instancio-junit</artifactId>
<version>5.5.1</version>
<scope>test</scope>
</dependency>
Basic Usage
Simple Object
final var order = Instancio.create(Order.class);
// All fields populated with random data
List of Objects
final var orders = Instancio.ofList(Order.class).size(5).create();
// 5 orders with random data
Customizing Values
Set Specific Fields
final var order = Instancio.of(Order.class)
.set(field(Order::getStatus), "PENDING")
.set(field(Order::getTotal), new BigDecimal("99.99"))
.create();
Supply Generated Values
final var order = Instancio.of(Order.class)
.supply(field(Order::getEmail), () -> "user" + UUID.randomUUID() + "@test.com")
.create();
Ignore Fields
final var order = Instancio.of(Order.class)
.ignore(field(Order::getId)) // Let DB generate
.create();
Complex Objects
Nested Objects
final var order = Instancio.of(Order.class)
.set(field(Order::getCustomer), Instancio.create(Customer.class))
.set(field(Order::getItems), Instancio.ofList(OrderItem.class).size(3).create())
.create();
All Fields Random
// When you need fully random but valid data
final var randomOrder = Instancio.create(Order.class);
// Customer, items, addresses - all populated
Spring Boot Integration
Repository Test Setup
@DataJpaTest
@AutoConfigureTestDatabase
@Testcontainers
class OrderRepositoryTest {
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:18");
@Autowired
private OrderRepository orderRepository;
@Test
void shouldFindOrdersByStatus() {
// Given: Create 10 random orders with PENDING status
final var orders = Instancio.ofList(Order.class)
.size(10)
.set(field(Order::getStatus), "PENDING")
.create();
orderRepository.saveAll(orders);
// When
final var found = orderRepository.findByStatus("PENDING");
// Then
assertThat(found).hasSize(10);
}
}
Controller Test Setup
@WebMvcTest(OrderController.class)
class OrderControllerTest {
@Autowired
private MockMvcTester mvc;
@MockitoBean
private OrderService orderService;
@Test
void shouldReturnOrder() {
// Given: Random order with specific ID
Order order = Instancio.of(Order.class)
.set(field(Order::getId), 1L)
.create();
given(orderService.findById(1L)).willReturn(order);
// When/Then
assertThat(mvc.get().uri("/orders/1"))
.hasStatus(HttpStatus.OK)
.bodyJson()
.convertTo(OrderResponse.class)
.satisfies(response -> {
assertThat(response.getId()).isEqualTo(1L);
});
}
}
Patterns
Builder Pattern Alternative
// Instead of:
Order order = Order.builder()
.id(1L)
.status("PENDING")
.customer(Customer.builder().name("John").build())
.items(List.of(
OrderItem.builder().product("A").price(10).build(),
OrderItem.builder().product("B").price(20).build()
))
.build();
// Use:
Order order = Instancio.of(Order.class)
.set(field(Order::getId), 1L)
.set(field(Order::getStatus), "PENDING")
.create();
// Customer and items auto-generated
Seeded Data
// Consistent "random" data for reproducible tests
Order order = Instancio.of(Order.class)
.withSeed(12345L)
.create();
// Same data every test run with seed 12345
Common Patterns
Email Generation
String email = Instancio.gen().net().email();
Date Generation
LocalDateTime createdAt = Instancio.gen().temporal()
.localDateTime()
.past()
.create();
String Patterns
String phone = Instancio.gen().text().pattern("+1-###-###-####");
Comparison
| Approach | Lines of Code | Maintainability |
|---|---|---|
| Manual setters | 10-20 | Low |
| Builder pattern | 5-10 | Medium |
| Instancio | 2-5 | High |
Best Practices
- Use for 3+ property objects - Not worth it for simple objects
- Set only what's relevant - Let Instancio fill the rest
- Use with Testcontainers - Great for database seeding
- Set IDs explicitly - When testing specific scenarios
- Ignore auto-generated fields - Like createdAt, updatedAt