← Назад к вопросам

Где должен быть установлен PostgreSQL для использования ег с Unit-тестами?

2.0 Middle🔥 111 комментариев
#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# PostgreSQL dlya Unit-Testov

Otvet: PostgreSQL NE dolzhen byt v unit-testah

Eto chastyj oshibka v integratsii! Unit-testy NE dolzhny zavisyet ot vneshnih resursov, vkluchaya bazy dannyh. Dlya testirovaniya po dannym s BD nado ispolzovat:

  1. In-Memory bazy dannyh (H2, SQLite)
  2. TestContainers (Docker kontejnery)
  3. Mock/Stub dlya BD
  4. Integration testy, ne unit-testy

Klassifikaciya testov

Unit-Testy           Integration-Testy    E2E Testy
- Bez zavisimostej   - C zavisimost'yu    - Realnyj okruzhenie
- V pamyati          - Testy s BD         - Polnyj stsenatrij
- Bystrye            - Medilenno          - Ochen medilenno
- Ne nuzen DB        - Mozhno s Docker    - Nuzen PostgreSQL

Sposob 1: H2 - In-Memory baza

Samyj bystroje resheniye dlya unit-testov. H2 - in-memory SQL baza.

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>test</scope>
</dependency>
@SpringBootTest
@DataJpaTest
public class UserRepositoryTest {
    
    @Autowired
    private UserRepository userRepository;
    
    @Test
    public void testSaveUser() {
        User user = new User();
        user.setEmail("test@example.com");
        user.setName("Test User");
        
        User saved = userRepository.save(user);
        
        assertNotNull(saved.getId());
        assertEquals("test@example.com", saved.getEmail());
    }
    
    @Test
    public void testFindByEmail() {
        User user = new User();
        user.setEmail("find@example.com");
        userRepository.save(user);
        
        Optional<User> found = userRepository.findByEmail("find@example.com");
        
        assertTrue(found.isPresent());
        assertEquals("find@example.com", found.get().getEmail());
    }
}
spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password:
  jpa:
    database-platform: org.hibernate.dialect.H2Dialect
    hibernate:
      ddl-auto: create-drop

Sposob 2: TestContainers - Real PostgreSQL v Docker

Dlya bolshej tochnosti mozhno ispolzovat realnyj PostgreSQL v Docker kontejnere.

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>testcontainers</artifactId>
    <version>1.17.6</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql</artifactId>
    <version>1.17.6</version>
    <scope>test</scope>
</dependency>
@SpringBootTest
public class UserRepositoryIntegrationTest {
    
    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>()
        .withDatabaseName("testdb")
        .withUsername("sa")
        .withPassword("sa")
        .withInitScript("init.sql");
    
    @Autowired
    private UserRepository userRepository;
    
    @Test
    public void testSaveAndFindUser() {
        User user = new User();
        user.setEmail("postgres@example.com");
        user.setName("Postgres User");
        
        User saved = userRepository.save(user);
        Optional<User> found = userRepository.findById(saved.getId());
        
        assertTrue(found.isPresent());
        assertEquals("postgres@example.com", found.get().getEmail());
    }
    
    @DynamicPropertySource
    static void postgresqlProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.datasource.username", postgres::getUsername);
        registry.add("spring.datasource.password", postgres::getPassword);
    }
}

Sposob 3: Mock Repository - Bez BD voobrazhae

Dlya chistyh unit-testov BIZ-logiki, mock'irun BD.

public class UserServiceTest {
    
    @Mock
    private UserRepository userRepository;
    
    @InjectMocks
    private UserService userService;
    
    @Before
    public void setUp() {
        MockitoAnnotations.openMocks(this);
    }
    
    @Test
    public void testGetUserById() {
        Long userId = 1L;
        User mockUser = new User();
        mockUser.setId(userId);
        mockUser.setEmail("mock@example.com");
        
        when(userRepository.findById(userId))
            .thenReturn(Optional.of(mockUser));
        
        User result = userService.getUserById(userId);
        
        assertNotNull(result);
        assertEquals("mock@example.com", result.getEmail());
        verify(userRepository, times(1)).findById(userId);
    }
    
    @Test
    public void testGetUserById_NotFound() {
        Long userId = 999L;
        
        when(userRepository.findById(userId))
            .thenReturn(Optional.empty());
        
        assertThrows(UserNotFoundException.class, 
            () -> userService.getUserById(userId));
    }
}

Sravnenie podhodov

PodkhodSpeedTochnostZavisimostDlya testov
H2Ochen bystrojSrednyayaNetUnit
TestContainersMedilennoVysokayaDockerIntegration
MockOchen bystrojDlya logikiNetUnit
Real PostgreSQLMedilennoIdealnaYesManual

Kak strukturirovat testy

src/test/java/
├── unit/                        # Unit-testy
│   ├── UserServiceTest.java     # Mock repository
│   ├── PaymentCalculatorTest.java
│   └── ValidatorTest.java
├── integration/                 # Integration-testy
│   ├── UserRepositoryTest.java  # H2 ili TestContainers
│   ├── PaymentServiceTest.java
│   └── NotificationServiceTest.java
└── e2e/                         # E2E testy
    └── FullOrderFlowTest.java   # Real environment

Primer s razdeleniem

// UNIT TEST - bez BD
@DisplayName("UserService Unit Tests")
public class UserServiceUnitTest {
    @Mock
    private UserRepository repository;
    @InjectMocks
    private UserService service;
    
    @Test
    public void testCreateUser_ValidEmail() {
        // Test biznes-logika, ne repository
    }
}

// INTEGRATION TEST - s BD
@SpringBootTest
@DisplayName("UserRepository Integration Tests")
public class UserRepositoryIntegrationTest {
    @Autowired
    private UserRepository repository;
    
    @Test
    public void testPersistence() {
        // Test BD operacii s H2 ili TestContainers
    }
}

Rekomendovannaya struktura project'a

<!-- pom.xml -->
<dependencies>
    <!-- Production -->
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.5.0</version>
    </dependency>
    
    <!-- Test: Unit-testy -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <scope>test</scope>
    </dependency>
    
    <!-- Test: Integration-testy -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.testcontainers</groupId>
        <artifactId>postgresql</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Luchshie praktiki

Ok UNIT-testy dolzhny NE zavisyet ot BD Ok Ispolzuj H2 dlya bystryh integration-testov Ok Ispolzuj TestContainers dlya bolshej tochnosti Ok Mock'irun repository dlya unit-testov service-sloyu Ok Real PostgreSQL tolko dlya manual-testirovaniya ili e2e Ok Otdelya unit i integration testy Ok Ispolzuj @DataJpaTest dlya tesztirovaniya JPA Ok Ispolzuj @SpringBootTest dlya integration-testov

Oshibki, kotoryh nado izbegat

Ne instaliruй PostgreSQL specifialno dlya unit-testov Ne ispolzuj real BD v CI/CD pipeline Ne piši unit-testy, kotorye zavysya ot BD Ne zabuvaj vychistvat BD posle testov Ne ispolzuj odnu BD instanciyu dlya parallelnyh testov

Zaklyuchenie

PostgreSQL - dlya production ili integration-testov v TestContainers Dlya unit-testov ispolzuj H2 ili mock'irun zavisimosti Realnyj PostgreSQL na vashem mashyne/servere - tolko dlya manual-testirovaniya CI/CD pipeline dolzhen ispolzovat izolirovannyh BD (Docker ili H2)

Где должен быть установлен PostgreSQL для использования ег с Unit-тестами? | PrepBro