15- Unit Testing ve JUnit

### Java'da Test Yazma ve Test Otomasyonu


Java'da test yazma ve test otomasyonu, yazılım geliştirme sürecinde kaliteyi sağlamak için önemlidir. Bu ders notları, JUnit kullanarak test yazma, test otomasyonu ve test kapsamı, ve mocking ile test verileri konularını kapsamaktadır.


---


### JUnit Kullanarak Test Yazma


JUnit, Java için en yaygın kullanılan test çerçevesidir. Birim testleri yazmak ve çalıştırmak için kullanılır. JUnit, test metotlarını işaretlemek ve test sonuçlarını doğrulamak için çeşitli anotasyonlar ve asserterler sağlar.


#### JUnit 5 Temel Kullanım


JUnit 5, JUnit 4'ün yeni bir versiyonudur ve bazı gelişmiş özellikler sunar.


1. **Test Sınıfı ve Metodları**


```java

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;


public class CalculatorTest {


    @Test

    void additionTest() {

        Calculator calculator = new Calculator();

        int result = calculator.add(2, 3);

        assertEquals(5, result, "2 + 3 should equal 5");

    }

}

```


- **`@Test`**: Test metotlarını işaretler.

- **`assertEquals(expected, actual, message)`**: Beklenen değeri ve gerçek değeri karşılaştırır.


2. **Test Başlatma ve Temizleme**


- **`@BeforeEach`**: Her test metodu çalışmadan önce çağrılır.

- **`@AfterEach`**: Her test metodu çalıştıktan sonra çağrılır.


```java

import org.junit.jupiter.api.BeforeEach;

import org.junit.jupiter.api.AfterEach;

import org.junit.jupiter.api.Test;


public class CalculatorTest {

    private Calculator calculator;


    @BeforeEach

    void setUp() {

        calculator = new Calculator();

    }


    @AfterEach

    void tearDown() {

        calculator = null;

    }


    @Test

    void additionTest() {

        int result = calculator.add(2, 3);

        assertEquals(5, result);

    }

}

```


- **`@BeforeAll`**: Sınıf seviyesinde, tüm testlerden önce bir kez çalışır.

- **`@AfterAll`**: Sınıf seviyesinde, tüm testlerden sonra bir kez çalışır.


```java

import org.junit.jupiter.api.AfterAll;

import org.junit.jupiter.api.BeforeAll;

import org.junit.jupiter.api.Test;


public class CalculatorTest {


    @BeforeAll

    static void initAll() {

        System.out.println("Before all tests");

    }


    @AfterAll

    static void tearDownAll() {

        System.out.println("After all tests");

    }


    @Test

    void additionTest() {

        // Test kodu

    }

}

```


---


### Test Otomasyonu ve Test Kapsamı


Test otomasyonu, manuel testlerin otomatikleştirilmesini ve sürekli entegrasyon sürecinin bir parçası olarak testlerin düzenli olarak çalıştırılmasını sağlar. Test kapsamı ise kodun ne kadarının test edildiğini belirler.


#### Test Otomasyonu


Test otomasyonu genellikle bir sürekli entegrasyon (CI) aracıyla birlikte kullanılır. Jenkins, GitHub Actions, GitLab CI gibi araçlar bu amaçla kullanılır.


- **Jenkins**: Testlerin otomatik olarak çalıştırılmasını sağlayan popüler bir CI/CD aracıdır.

- **GitHub Actions**: GitHub'da otomatik test ve dağıtım süreçlerini tanımlar.


**Örnek Jenkins Pipeline Konfigürasyonu:**


```groovy

pipeline {

    agent any

    stages {

        stage('Build') {

            steps {

                sh './gradlew build'

            }

        }

        stage('Test') {

            steps {

                sh './gradlew test'

            }

        }

        stage('Deploy') {

            steps {

                sh './deploy.sh'

            }

        }

    }

}

```


#### Test Kapsamı


Test kapsamı, genellikle kodun hangi kısmının test edildiğini ölçer. Kod kapsamını artırmak için kullanılan araçlar:


- **JaCoCo**: Java için bir kod kapsamı analiz aracıdır.

- **Cobertura**: Kod kapsamı analiz aracıdır.


**JaCoCo Kullanımı:**


- **Gradle Konfigürasyonu:**


```groovy

plugins {

    id 'jacoco'

}


jacocoTestReport {

    reports {

        xml.enabled true

        html.enabled true

    }

}


test {

    finalizedBy jacocoTestReport

}

```


- **Maven Konfigürasyonu:**


```xml

<plugin>

    <groupId>org.jacoco</groupId>

    <artifactId>jacoco-maven-plugin</artifactId>

    <version>0.8.7</version>

    <executions>

        <execution>

            <goals>

                <goal>prepare-agent</goal>

                <goal>report</goal>

            </goals>

        </execution>

    </executions>

</plugin>

```


---


### Mocking ve Test Verileri


Mocking, testlerde bağımlılıkların taklit edilmesini sağlar ve testlerin izole edilmesine yardımcı olur. `Mockito` gibi kütüphaneler bu amaçla kullanılır.


#### Mockito Kullanımı


Mockito, Java için popüler bir mocking kütüphanesidir.


1. **Mock Nesneleri Oluşturma**


```java

import static org.mockito.Mockito.*;


public class MockingExample {

    public static void main(String[] args) {

        List<String> mockedList = mock(List.class);

        when(mockedList.get(0)).thenReturn("Hello, World!");


        System.out.println(mockedList.get(0)); // Çıktı: Hello, World!

        System.out.println(mockedList.get(1)); // Çıktı: null

    }

}

```


- **`mock(Class<T> classToMock)`**: Mock nesnesi oluşturur.

- **`when(T methodCall).thenReturn(V value)`**: Bir metodun geri dönüş değerini tanımlar.


2. **Veri Doğrulama**


```java

import static org.mockito.Mockito.*;


public class MockingExample {

    public static void main(String[] args) {

        List<String> mockedList = mock(List.class);


        mockedList.add("test");

        verify(mockedList).add("test");

    }

}

```


- **`verify(T mock).methodCall()`**: Bir metodun çağrıldığını doğrular.


3. **Spy Nesneleri**


Spy, gerçek nesnelerin üzerinde test yaparken kullanılır.


```java

import static org.mockito.Mockito.*;


public class SpyExample {

    public static void main(String[] args) {

        List<String> realList = new ArrayList<>();

        List<String> spyList = spy(realList);


        spyList.add("test");

        System.out.println(spyList.get(0)); // Çıktı: test


        verify(spyList).add("test");

    }

}

```


- **`spy(T object)`**: Gerçek bir nesnenin spy nesnesini oluşturur.


---


### Özet


Bu ders notları, Java'da JUnit kullanarak test yazma, test otomasyonu ve test kapsamı, ve mocking ile test verileri konularını kapsamaktadır. JUnit, birim testleri yazmak ve çalıştırmak için kullanılır. Test otomasyonu, sürekli entegrasyon araçları ile otomatikleştirilir. Mocking, bağımlılıkların taklit edilmesini sağlar ve testlerin izole edilmesine yardımcı olur. Bu bilgileri kullanarak, Java uygulamalarınızın kalitesini artırabilir ve etkili testler yazabilirsiniz.