Testing & Quality - bu kod "ishlayapti" degani bilan cheklanmaslik. Java developer kodni shunday yozishi kerakki:
1. bug tez topilsin
2. regression kamayadi
3. refactor qilish xavfsiz bo‘ladi
4. production’da kutilmagan xatolar kamayadi
5. code review’dan oson o‘tadiBu bo‘limga quyidagilar kiradi: Integration tests with @SpringBootTest, Testcontainers, WireMock, TDD approach, Static analysis: SonarQube, SpotBugs.
1. Testing nima uchun kerak?
Ko‘p juniorlar testni "ortiqcha ish" deb o‘ylaydi. Lekin real loyihada test quyidagilar uchun kerak:
eski feature buzilib qolmasligi;
yangi developer kodni xavfsiz o‘zgartirishi;
biznes qoida avtomatik tekshirilishi;
production bug kamayishi;
deploymentga ishonch oshishi.
Masalan, order yaratishda qoida bor:
Agar product stock’da yetarli bo‘lmasa, order yaratilmasin.Buni qo‘lda har safar tekshirish yomon. Test bilan avtomatik tekshiramiz.
2. Test turlari
Backend’da odatda 4 ta asosiy test turi bor:
Test turi | Nimani tekshiradi |
|---|---|
Unit test | Bitta class yoki method logic |
Integration test | Bir nechta component birga ishlashi |
Repository test | DB query va JPA mapping |
API/E2E test | HTTP endpoint to‘liq flow |
3. Unit Test
Unit test - kichik logicni alohida tekshiradi.
Masalan, discount hisoblash:
public class DiscountService {
public BigDecimal calculate(BigDecimal amount) {
if (amount.compareTo(BigDecimal.valueOf(100_000)) >= 0) {
return amount.multiply(BigDecimal.valueOf(0.1));
}
return BigDecimal.ZERO;
}
}Test:
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import static org.junit.jupiter.api.Assertions.assertEquals;
class DiscountServiceTest {
private final DiscountService discountService = new DiscountService();
@Test
void shouldReturnTenPercentDiscountWhenAmountIsGreaterThan100000() {
BigDecimal discount = discountService.calculate(BigDecimal.valueOf(200_000));
assertEquals(BigDecimal.valueOf(20_000.0), discount);
}
@Test
void shouldReturnZeroWhenAmountIsLessThan100000() {
BigDecimal discount = discountService.calculate(BigDecimal.valueOf(50_000));
assertEquals(BigDecimal.ZERO, discount);
}
}Bu test Spring context ochmaydi. Tez ishlaydi.
4. Unit Test qachon yoziladi?
Unit test quyidagilar uchun yaxshi:
business rule
calculation
validation logic
mapper logic
state transition
utility method
domain methodMasalan:
order status
NEW → CONFIRMED;discount calculation;
payment fee calculation;
phone validation;
date range validation;
permission check.
5. JUnit 5 asoslari
JUnit 5'da asosiy annotationlar:
Annotation | Vazifasi |
|---|---|
| Test method |
| Har testdan oldin ishlaydi |
| Har testdan keyin ishlaydi |
| Barcha testlardan oldin bir marta |
| Barcha testlardan keyin bir marta |
| Testga tushunarli nom |
| Parametrli test |
6. @BeforeEach
class OrderServiceTest {
private OrderService orderService;
@BeforeEach
void setUp() {
orderService = new OrderService();
}
@Test
void shouldCreateOrder() {
// test
}
}Har testdan oldin yangi holat tayyorlanadi.
7. Assertions
Eng ko‘p ishlatiladigan assertionlar:
assertEquals(expected, actual);
assertTrue(condition);
assertFalse(condition);
assertNotNull(object);
assertNull(object);
assertThrows(Exception.class, () -> method());Exception test:
@Test
void shouldThrowExceptionWhenStockIsNotEnough() {
Product product = new Product("Laptop", 1);
IllegalStateException exception = assertThrows(
IllegalStateException.class,
() -> product.decreaseStock(5)
);
assertEquals("Stock yetarli emas", exception.getMessage());
}8. Mockito nima?
Mockito - dependency’larni fake qilish uchun ishlatiladi.
Masalan, OrderService ichida ProductRepository bor:
@Service
public class OrderService {
private final ProductRepository productRepository;
public OrderService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public OrderDto createOrder(Long productId, int quantity) {
Product product = productRepository.findById(productId)
.orElseThrow(() -> new RuntimeException("Product topilmadi"));
product.decreaseStock(quantity);
return new OrderDto(product.getId(), quantity);
}
}Unit testda haqiqiy DB kerak emas. Repository’ni mock qilamiz.
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
class OrderServiceTest {
private final ProductRepository productRepository = Mockito.mock(ProductRepository.class);
private final OrderService orderService = new OrderService(productRepository);
@Test
void shouldCreateOrder() {
Product product = new Product(1L, "Laptop", 10);
when(productRepository.findById(1L))
.thenReturn(Optional.of(product));
OrderDto result = orderService.createOrder(1L, 2);
assertEquals(1L, result.productId());
assertEquals(2, result.quantity());
}
}9. Mockito bilan verify
verify() method chaqirilganini tekshiradi.
verify(productRepository).findById(1L);Masalan:
@Test
void shouldCallRepository() {
Product product = new Product(1L, "Laptop", 10);
when(productRepository.findById(1L))
.thenReturn(Optional.of(product));
orderService.createOrder(1L, 2);
verify(productRepository).findById(1L);
}Lekin verify()ni haddan tashqari ko‘p ishlatish ham yomon. Test implementationga qattiq bog‘lanib qoladi.
10. Mock qachon kerak?
Mock quyidagilar uchun kerak:
repository
external client
email sender
SMS sender
payment provider
file storage
queue producerLekin oddiy domain objectlarni mock qilish shart emas. Real object ishlatish yaxshiroq.
Yomon:
Product product = mock(Product.class);Yaxshi:
Product product = new Product("Laptop", 10);11. Unit Test yaxshi yozish qoidasi
Test odatda 3 qismdan iborat:
Arrange - test uchun data tayyorlash
Act - methodni chaqirish
Assert - natijani tekshirishMisol:
@Test
void shouldDecreaseStock() {
// Arrange
Product product = new Product("Laptop", 10);
// Act
product.decreaseStock(3);
// Assert
assertEquals(7, product.getStock());
}12. Test nomlash
Yomon:
@Test
void test1() {}Yaxshi:
@Test
void shouldDecreaseStockWhenQuantityIsAvailable() {}Yoki:
@Test
@DisplayName("Stock yetarli bo‘lsa product stock kamayishi kerak")
void shouldDecreaseStockWhenQuantityIsAvailable() {}Test nomidan nimani tekshirayotgani bilinishi kerak.
13. Integration Test
Integration test - bir nechta component birga ishlashini tekshiradi.
Masalan:
Service + Repository + Database
Controller + Service + Validation
Spring Security + JWT filter
Repository + PostgreSQLUnit test tez, lekin hamma narsani ushlamaydi. Integration test realroq muhit beradi.
14. @SpringBootTest
@SpringBootTest butun Spring contextni ochadi.
@SpringBootTest
class OrderServiceIntegrationTest {
@Autowired
private OrderService orderService;
@Test
void shouldCreateOrder() {
// real Spring beanlar bilan test
}
}Afzalligi:
real beanlar ishlaydi;
dependency injection ishlaydi;
transaction, validation, eventlar tekshiriladi.
Kamchiligi:
sekinroq;
context ochiladi;
noto‘g‘ri ishlatilsa testlar og‘irlashadi.
15. @DataJpaTest
Repository va JPA mapping test qilish uchun.
@DataJpaTest
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void shouldFindByEmail() {
User user = new User("Ali", "ali@example.com");
userRepository.save(user);
Optional<User> result = userRepository.findByEmail("ali@example.com");
assertTrue(result.isPresent());
}
}Bu faqat JPA bilan bog‘liq beanlarni ochadi. @SpringBootTestdan yengilroq.
16. @WebMvcTest
Controller test qilish uchun.
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockitoBean
private UserService userService;
@Test
void shouldReturnUser() throws Exception {
when(userService.getById(1L))
.thenReturn(new UserDto(1L, "Ali"));
mockMvc.perform(get("/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Ali"));
}
}Bu HTTP layerni test qiladi:
URL mapping;
request/response;
validation;
status code;
JSON structure.
17. MockMvc
MockMvc real server ko‘tarmasdan HTTP requestni test qiladi.
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"name": "Ali",
"email": "ali@example.com"
}
"""))
.andExpect(status().isOk());Validation error test:
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"name": "",
"email": "wrong-email"
}
"""))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value("VALIDATION_ERROR"));18. Testcontainers
Testcontainers - test paytida Docker container ochib, real dependency bilan test qilish.
Masalan:
PostgreSQL;
Redis;
Kafka;
RabbitMQ;
MongoDB;
Elasticsearch.
Bu juda muhim Middle-level skill.
19. Nega H2 o‘rniga Testcontainers?
Ko‘p loyihalarda test uchun H2 ishlatiladi. Lekin production PostgreSQL bo‘lsa, H2 bilan farqlar chiqishi mumkin.
Masalan:
PostgreSQL syntax boshqacha
JSONB H2'da yo‘q yoki boshqacha
index behavior farq qiladi
transaction isolation farq qiladi
sequence/identity farq qiladi
native query ishlamasligi mumkinShuning uchun production PostgreSQL bo‘lsa, testda ham PostgreSQL container ishlatish yaxshi.
20. PostgreSQL Testcontainer misol
Dependency:
testImplementation("org.testcontainers:junit-jupiter")
testImplementation("org.testcontainers:postgresql")Test:
@Testcontainers
@SpringBootTest
class UserRepositoryIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:16")
.withDatabaseName("test_db")
.withUsername("test")
.withPassword("test");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired
private UserRepository userRepository;
@Test
void shouldSaveAndFindUser() {
User user = new User("Ali", "ali@example.com");
userRepository.save(user);
Optional<User> result = userRepository.findByEmail("ali@example.com");
assertTrue(result.isPresent());
}
}Bu test haqiqiy PostgreSQL’da ishlaydi.
21. Redis Testcontainer
@Testcontainers
@SpringBootTest
class RedisCacheIntegrationTest {
@Container
static GenericContainer<?> redis =
new GenericContainer<>("redis:7")
.withExposedPorts(6379);
@DynamicPropertySource
static void redisProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.redis.host", redis::getHost);
registry.add("spring.data.redis.port", () -> redis.getMappedPort(6379));
}
@Test
void contextLoads() {
}
}22. WireMock
WireMock - tashqi HTTP API’larni fake qilish uchun.
Masalan:
Payment provider
SMS provider
Telegram bot API
CRM API
Eskiz SMS APITest paytida haqiqiy payment providerga request yuborish xavfli. WireMock bilan fake server ochamiz.
23. WireMock misol
Dependency:
testImplementation("org.springframework.cloud:spring-cloud-contract-wiremock")Test:
@SpringBootTest
@AutoConfigureWireMock(port = 0)
class PaymentClientTest {
@Autowired
private PaymentClient paymentClient;
@Test
void shouldCreatePayment() {
stubFor(post(urlEqualTo("/payments"))
.willReturn(aResponse()
.withHeader("Content-Type", "application/json")
.withBody("""
{
"status": "SUCCESS",
"transactionId": "trx-123"
}
""")));
PaymentResponse response = paymentClient.createPayment(
new PaymentRequest(BigDecimal.valueOf(100_000))
);
assertEquals("SUCCESS", response.status());
assertEquals("trx-123", response.transactionId());
}
}WireMock bilan tekshirish mumkin:
request qaysi URLga ketdi;
header to‘g‘rimi;
body to‘g‘rimi;
timeout holati;
500 error holati;
invalid response holati.
24. TDD approach
TDD - Test Driven Development.
TDD sikli:
1. Red - avval yiqiladigan test yozamiz
2. Green - test o‘tadigan minimal kod yozamiz
3. Refactor - kodni tozalaymizMasalan, talab:
Agar order summasi 100 000 dan katta bo‘lsa, 10% discount berilsin.Avval test:
@Test
void shouldApplyTenPercentDiscount() {
DiscountService service = new DiscountService();
BigDecimal result = service.calculate(BigDecimal.valueOf(200_000));
assertEquals(BigDecimal.valueOf(20_000.0), result);
}Keyin minimal kod:
public BigDecimal calculate(BigDecimal amount) {
return amount.multiply(BigDecimal.valueOf(0.1));
}Keyin yana test qo‘shamiz:
@Test
void shouldReturnZeroWhenAmountIsLessThan100000() {
DiscountService service = new DiscountService();
BigDecimal result = service.calculate(BigDecimal.valueOf(50_000));
assertEquals(BigDecimal.ZERO, result);
}Keyin kodni to‘g‘rilaymiz:
public BigDecimal calculate(BigDecimal amount) {
if (amount.compareTo(BigDecimal.valueOf(100_000)) >= 0) {
return amount.multiply(BigDecimal.valueOf(0.1));
}
return BigDecimal.ZERO;
}25. TDD qachon foydali?
TDD ayniqsa quyidagilarda foydali:
business rules
calculation
domain model
state machine
validation
edge cases
bug fixMasalan, bug chiqdi:
Cancelled order payment qilinib ketdi.Avval test yozamiz:
@Test
void shouldNotPayCancelledOrder() {
Order order = new Order();
order.cancel();
assertThrows(IllegalStateException.class, order::pay);
}Keyin bugni fix qilamiz. Shu test kelajakda bug qaytmasligini himoya qiladi.
26. Code Coverage
Code coverage - testlar kodning qancha qismini ishlatganini ko‘rsatadi.
Masalan:
Line coverage: 80%
Branch coverage: 65%Lekin coverage yuqori bo‘lsa ham, test sifati yaxshi degani emas.
Yomon test:
@Test
void test() {
service.create();
}Bu faqat method chaqiradi. Natijani tekshirmaydi.
Yaxshi test:
@Test
void shouldCreateOrderWithNewStatus() {
Order order = service.create();
assertEquals(OrderStatus.NEW, order.getStatus());
assertNotNull(order.getCreatedAt());
}Coverage maqsad emas, signal.
27. Static Analysis
Static analysis - kodni ishga tushirmasdan tekshiradi.
Topishi mumkin:
null pointer xavfi;
unused code;
duplicate code;
security issue;
code smell;
resource leak;
noto‘g‘ri equals/hashCode;
exception handling muammolari.
Static analysis uchun SonarQube va SpotBugs ishlatiladi.
28. SonarQube
SonarQube - code quality platform.
Tekshiradi:
bugs
vulnerabilities
code smells
coverage
duplications
security hotspots
maintainability
reliabilityMasalan, Sonar shunday ogohlantirishi mumkin:
if (user.getName().equals("Ali")) {
}Agar user.getName() null bo‘lsa, NPE.
Yaxshiroq:
if ("Ali".equals(user.getName())) {
}29. SpotBugs
SpotBugs - Java bytecode’dan bug patternlarni topadi.
Masalan:
null dereference;
bad equals;
ignored return value;
thread-safety issue;
resource leak.
Gradle dependency:
plugins {
id("com.github.spotbugs") version "6.0.0"
}30. Checkstyle va PMD
Qo‘shimcha quality toollar:
Tool | Vazifasi |
|---|---|
Checkstyle | code style qoidalari |
PMD | code smell va oddiy buglar |
SpotBugs | bytecode asosida bug pattern |
SonarQube | umumiy quality dashboard |
31. Test Data Builder
Testlarda object yaratish ko‘payib ketadi.
Yomon:
User user = new User(
"Ali",
"ali@example.com",
UserStatus.ACTIVE,
LocalDateTime.now(),
true
);Har testda qaytarilsa, charchatadi.
Yaxshi: test data builder.
public class UserTestBuilder {
private String name = "Ali";
private String email = "ali@example.com";
private UserStatus status = UserStatus.ACTIVE;
public static UserTestBuilder user() {
return new UserTestBuilder();
}
public UserTestBuilder withEmail(String email) {
this.email = email;
return this;
}
public UserTestBuilder inactive() {
this.status = UserStatus.INACTIVE;
return this;
}
public User build() {
return new User(name, email, status);
}
}Ishlatish:
User activeUser = UserTestBuilder.user().build();
User inactiveUser = UserTestBuilder.user()
.inactive()
.build();
User customEmailUser = UserTestBuilder.user()
.withEmail("vali@example.com")
.build();32. Testlarda database tozalash
Integration testlarda testlar bir-biriga ta’sir qilmasligi kerak.
Yomon:
1-test user yaratadi
2-test shu user qolganidan yiqiladiYechimlar:
@Transactional
@DataJpaTest
@Transactional
class UserRepositoryTest {
}Test tugaganda rollback bo‘ladi.
@Sql
@Sql(scripts = "/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)Repository delete
@AfterEach
void cleanUp() {
userRepository.deleteAll();
}Katta loyihada Testcontainers + migration + cleanup strategiya aniq bo‘lishi kerak.
33. Flaky Test
Flaky test - ba’zida o‘tadi, ba’zida yiqiladi.
Sabablar:
vaqtga bog‘liq test
thread/asynchronous code
external API
shared database state
random data
test orderga bog‘liqlik
sleep ishlatishYomon:
Thread.sleep(1000);
assertTrue(notificationSent);Yaxshiroq:
await()
.atMost(Duration.ofSeconds(5))
.untilAsserted(() -> assertTrue(notificationSent));Buning uchun Awaitility ishlatiladi.
34. Async code test qilish
Dependency:
testImplementation("org.awaitility:awaitility")Misol:
@Test
void shouldSendNotificationAsync() {
orderService.createOrder(request);
await()
.atMost(Duration.ofSeconds(5))
.untilAsserted(() -> {
verify(notificationService).send(any());
});
}Thread.sleep() o‘rniga Awaitility yaxshi.
35. Test piramidasi
Yaxshi loyiha testlari taxminan shunday bo‘ladi:
Ko‘p: Unit tests
O‘rtacha: Integration tests
Kamroq: Full end-to-end testsChunki:
unit test tez;
integration test sekinroq, lekin realroq;
E2E test eng sekin va fragile.
36. Qaysi testni qachon yozish kerak?
Holat | Test turi |
|---|---|
Business calculation | Unit test |
Entity domain method | Unit test |
Repository query |
|
Controller validation |
|
Full API flow |
|
External API client | WireMock |
Redis/Kafka/Postgres | Testcontainers |
Async event | Awaitility |
Security permission | WebMvc/SpringBootTest |
37. Real misol: Order yaratish uchun test strategiya
Feature:
User order yaratadi.
Stock yetarli bo‘lsa order CONFIRMED bo‘ladi.
Stock kamayadi.
Agar stock yetarli bo‘lmasa exception chiqadi.Testlar:
Unit test - Product
@Test
void shouldDecreaseStock() {
Product product = new Product("Laptop", 10);
product.decreaseStock(3);
assertEquals(7, product.getStock());
}Unit test - stock yetarli emas
@Test
void shouldThrowExceptionWhenStockIsNotEnough() {
Product product = new Product("Laptop", 2);
assertThrows(
IllegalStateException.class,
() -> product.decreaseStock(5)
);
}Integration test - OrderService
@SpringBootTest
@Testcontainers
class OrderServiceIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:16");
@DynamicPropertySource
static void properties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired
private OrderService orderService;
@Test
void shouldCreateOrderWhenStockIsEnough() {
CreateOrderRequest request = new CreateOrderRequest(/* ... */);
OrderDto result = orderService.create(request);
assertEquals(OrderStatus.CONFIRMED, result.status());
}
}38. Global Exception Handler test
Controller noto‘g‘ri request kelsa 400 Bad Request qaytarishi kerak.
@WebMvcTest(UserController.class)
class UserControllerValidationTest {
@Autowired
private MockMvc mockMvc;
@MockitoBean
private UserService userService;
@Test
void shouldReturnBadRequestWhenEmailInvalid() throws Exception {
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"name": "Ali",
"email": "wrong-email"
}
"""))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value("VALIDATION_ERROR"));
}
}39. Security test
Admin endpoint faqat admin uchun ochiq bo‘lsin.
@WebMvcTest(AdminController.class)
class AdminControllerSecurityTest {
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser(roles = "ADMIN")
void shouldAllowAdmin() throws Exception {
mockMvc.perform(get("/admin/users"))
.andExpect(status().isOk());
}
@Test
@WithMockUser(roles = "USER")
void shouldForbidUser() throws Exception {
mockMvc.perform(get("/admin/users"))
.andExpect(status().isForbidden());
}
}40. Testlarda eng ko‘p xatolar
1. Test faqat coverage uchun yoziladi
Yomon:
@Test
void testCreate() {
service.create(request);
}Assert yo‘q. Foydasi kam.
2. Hamma narsani mock qilish
Yomon:
Order order = mock(Order.class);
Product product = mock(Product.class);
User user = mock(User.class);Domain objectlar real bo‘lsin. Tashqi dependencylar mock bo‘lsin.
3. @SpringBootTestni har joyda ishlatish
Yomon:
@SpringBootTest
class DiscountServiceTest {
}Agar oddiy calculation bo‘lsa, Spring context kerak emas.
Yaxshi:
class DiscountServiceTest {
private final DiscountService service = new DiscountService();
}4. Testlar bir-biriga bog‘liq
Yomon:
test1 user yaratadi
test2 shu user bor deb kutadiHar test mustaqil bo‘lishi kerak.
5. Real external API chaqirish
Yomon:
paymentClient.pay(realCard);Testda real payment, real SMS, real email ishlatish xavfli.
Yaxshi:
WireMock
MockBean
Fake implementation41. CI/CD’da test
Real loyihada testlar pipeline’da ishlaydi:
git push
↓
build
↓
unit tests
↓
integration tests
↓
static analysis
↓
docker image
↓
deployAgar test yiqilsa, deploy to‘xtaydi.
Bu productionni himoya qiladi.
42. Gradle’da test commandlar
./gradlew testSpotBugs:
./gradlew spotbugsMainCheckstyle:
./gradlew checkstyleMainBarchasi:
./gradlew clean build43. Pull Request quality checklist
PR ochishdan oldin:
1. Unit testlar o‘tdimi?
2. Integration testlar o‘tdimi?
3. Yangi business rule uchun test bormi?
4. Validation error test qilinganmi?
5. Security permission test qilinganmi?
6. Static analysis xatolari yo‘qmi?
7. Code duplication yo‘qmi?
8. Loglar to‘g‘rimi?
9. Sensitive data logga chiqmayaptimi?
10. Testlar flaky emasmi?44. Java Developer uchun minimal checklist
Testing & Quality bo‘yicha biz quyidagilarni bilishimiz kerak:
JUnit 5
Mockito
unit test
integration test
@SpringBootTest
@DataJpaTest
@WebMvcTest
MockMvc
Testcontainers
WireMock
Awaitility
TDD asoslari
code coverage
SonarQube
SpotBugs
Checkstyle/PMD
test data builder
flaky test sabablari
CI’da test ishlashi45. Interview savollari
Unit test va integration test farqi?
Unit test bitta kichik logicni alohida tekshiradi. Integration test bir nechta component birga ishlashini tekshiradi.
Mock nima?
Real dependency o‘rniga test uchun fake object.
Mockito qachon ishlatiladi?
Repository, external API client, email sender kabi dependencylarni fake qilish uchun.
@SpringBootTest nima qiladi?
Butun Spring contextni ochadi va real beanlar bilan test qilish imkonini beradi.
@DataJpaTest nima uchun?
Repository va JPA mapping testlari uchun.
Testcontainers nima?
Test paytida Docker containerlarda real dependency, masalan PostgreSQL yoki Redis, ishga tushirib beradi.
WireMock nima?
Tashqi HTTP API’larni fake qilish uchun ishlatiladi.
TDD nima?
Avval test yozish, keyin testdan o‘tadigan kod yozish, so‘ng refactor qilish yondashuvi.
Code coverage 100% bo‘lsa, kod sifatli deganimi?
Yo‘q. Coverage faqat testlar kodni necha foiz ishlatganini ko‘rsatadi. Testlar assert qilmasa, coverage foydasiz bo‘lishi mumkin.
Flaky test nima?
Ba’zida o‘tib, ba’zida yiqiladigan ishonchsiz test.
Qisqa xulosa
Testing & Quality - Java developer uchun majburiy skill.
Junior ko‘pincha shunday qiladi:
kod yozdim
Postman’da tekshirdim
ishladiMiddle esa shunday o‘ylaydi:
business rule test bilan himoyalanganmi?
repository query real DBda ishlaydimi?
validation response to‘g‘rimi?
external API WireMock bilan test qilinganmi?
Testcontainers orqali PostgreSQL tekshirildimi?
Sonar/SpotBugs xatolari yo‘qmi?
CI pipeline’da test o‘tadimi?Eng muhim 5 ta joy:
1. Unit test - business logic uchun
2. Integration test - Spring + DB uchun
3. Testcontainers - real dependency uchun
4. WireMock - external API uchun
5. Static analysis - code quality uchun