Sobes.tech
Middle

What types of tests do you write and how?

sobes.tech AI

Answer from AI

I write the following types of tests:

  • Unit tests: Test individual components (classes, methods) in isolation. I use JUnit or TestNG, mocks with Mockito.
  • Integration tests: Check interaction between multiple components or subsystems (e.g., service with database). I often use Spring Boot Test and Testcontainers.
  • Component tests: Cover functionality of a specific component of the system as a whole, including its interaction with external dependencies (often mocked).
  • End-to-End (E2E) tests: Test the complete operation of the entire system from start to finish, simulating user actions. They may use Selenium, Cypress (for web).

Test writing process:

  1. Understanding requirements: Clearly define what the code under test should do.
  2. Choosing test type: Determine which type of test is most suitable for the functionality (Unit, Integration, etc.).
  3. Setting up test environment: Prepare necessary dependencies, mocks, test data.
  4. Writing test scenario: Define sequence of actions and expected result.
  5. Writing test code: Implement the test scenario using the chosen framework.
  6. Running the test: Execute the test and ensure it passes successfully.
  7. Refactoring the test: Improve readability and maintainability if needed.

Example of a Unit test with Mockito:

// Imports omitted for brevity

public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    void testGetUserById_Success() {
        // Prepare data
        long userId = 1L;
        User mockUser = new User(userId, "testuser");
        when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));

        // Execute the method under test
        Optional<User> result = userService.getUserById(userId);

        // Verify the result
        assertTrue(result.isPresent());
        assertEquals("testuser", result.get().getUsername());
        verify(userRepository, times(1)).findById(userId); // Verify repository method was called once
    }

    @Test
    void testGetUserById_NotFound() {
        // Prepare data
        long userId = 2L;
        when(userRepository.findById(userId)).thenReturn(Optional.empty());

        // Execute the method under test
        Optional<User> result = userService.getUserById(userId);

        // Verify the result
        assertFalse(result.isPresent());
        verify(userRepository, times(1)).findById(userId);
    }
}

Example of an Integration test with Spring Boot Test and Testcontainers:

// Imports omitted for brevity

@SpringBootTest
@Testcontainers
public class UserRepositoryIntegrationTest {

    @Container
    private static PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer<>("postgres:13")
            .withDatabaseName("testdb")
            .withUsername("test")
            .withPassword("test");

    @Autowired
    private UserRepository userRepository;

    @DynamicPropertySource
    static void configureProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgresContainer::getJdbcUrl);
        registry.add("spring.datasource.username", postgresContainer::getUsername);
        registry.add("spring.datasource.password", postgresContainer::getPassword);
    }

    @Test
    void testSaveAndFindUser() {
        // Create test user
        User newUser = new User(null, "integration_user");

        // Save user
        User savedUser = userRepository.save(newUser);
        assertNotNull(savedUser.getId());

        // Find user
        Optional<User> foundUserOptional = userRepository.findById(savedUser.getId());
        assertTrue(foundUserOptional.isPresent());
        User foundUser = foundUserOptional.get();
        assertEquals("integration_user", foundUser.getUsername());
    }
}