6 Kasım 2013 Çarşamba

Junit&PowerMock ile static && void metodları mocklamaca & test etmece

Selamlar,

Başlıkta tarif edilen ve tekrar aşağıya yazmaya üşenilen durum için aşağıdaki kodu kullandım, isteyen alabilir ;)

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import java.math.BigDecimal;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({MyStaticClassEx.class})
public class MyTest
{
protected MyStaticClassEx mockMyStaticClassEx;
protected Request request = new Request();
protected Long longNumber = new Long( 333 );

@Before
public void setUp() throws Exception {
// fill Request object
// ...
mockMyStaticClassEx();
}

public void mockMyStaticClassEx()
{
mockMyStaticClassEx = PowerMockito.mock( MyStaticClassEx.class );
                PowerMockito.when( mockMyStaticClassEx.getId() ).thenReturn( longNumber );
// void method mocking
PowerMockito.doNothing().when( mockMyStaticClassEx ).insertCouponActivity( Mockito.anyLong(), Mockito.anyLong() );

PowerMockito.mockStatic( MyStaticClassEx.class );
                // static method
PowerMockito.when( MyStaticClassEx.getInstance() ).thenReturn( mockMyStaticClassEx );
}

@Test
public void test() throws Exception {

try {
Response response = MainClass.getReq( request );
assertEquals( true, response.result() );
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
assertFalse(true);
}

}
}

Classpath'i aynı olan ve iki farklı JAR'da bulunan sınıflardan hangisinin kullanılacağına karar vermece

Selamlar,

Eğer projenizde aynı classpath'e ve isme sahip, farklı JARlarda bulunan iki sınıfınız var ise, IDEmiz pom.xml'de üstte olan JAR'dan import ediyor bu sınıfı. Yani, eğer diğer JARdaki sınıfı import etmek isterseniz, pom.xml'de dependency olarak diğer JAR tanımının üstüne taşımanız yeterli olacaktır.

Bilginize...

8 Ocak 2012 Pazar

HTMLParser Kullanımı

Merhabalar,

Html dosyalarını parse etmek birçoğumuz için güncel bir sorundur. Bu sorunu HtmlParser kütüphanesi ile aşabiliriz.

Öncelikle http://sourceforge.net/projects/htmlparser/files/htmlparser/1.6/htmlparser1_6_20060610.zip/download adresinden gerekli dosyaları indiriyoruz. Bu dosyaların içinde HtmlParser için 2 adet jar dosyaları bulunmakta, bunları projemize ekliyoruz.

Aşağıdaki kod ile, belirttiğimiz tagler arasındaki(örneğimizde "a") verileri string arrayine atabiliyoruz.

...
...

Parser parser = new Parser("C:\\Users\\Emre\\WorkspaceDeneme\\TopicModelingTool\\output_html\\all_topics.html");
NodeList nl = parser.parse(null);
NodeList div = nl.extractAllNodesThatMatch(new TagNameFilter("a"),true);
String[][] str = new String[div.size()][];
Set<String> s=new TreeSet<String>();




for(int i=0;i<div.size();i++) {
    NodeList nodes = div.elementAt(i).getChildren();
    str[i] = nodes.asString().split(" "); 
}
...
...

İyi günler.

19 Ağustos 2011 Cuma

Junit ve Mockit ile Private ve Void Methodları Test Etme

Arkadaşlar Merhabalar,

Projeleri test ederken karşılaştığımız bir problem de private ve void methodların özel durumlarıdır. Private methoda erişemediğimizden, Void methodun da birşey döndürmediğinden bu sonuç ortaya çıkar. Void method için aslında yapılabilecek çok bir şey yok, kullandığı global değişkenleri Mockit kütüphanesinin getField() fonksiyonu ile kontrol edebiliriz.

String actual = getField(instance, "exportData");

actual : Kontrol edeceğimiz parametre
instance : Parametresini çekeceğimiz obje

exportData : Parametrenin adı

Bundan sonra assertEqual fonksiyonu ile karşılaştırma yapılabilir. Private methodları çağırmak için de aşağıdaki kodu kullanabiliriz.

...
...
                Class c = Class.forName("com.layers.drivers.DataDriverImpl");
                Method methodParse = c.getDeclaredMethod("parseDataToExportData", new Class[]{Collection.class,Collection.class}); // Fonksiyonun adı ve aldığı parametrelerin tipi
                methodParse.setAccessible(true);
                Object objParse = c.newInstance();
                setField(objParse, "dataExportData", mockDataExportData); // Fonksiyonun kullandığı bir global parametreyi kendi parametremizle değiştirme               
                methodParse.invoke(objParse, new Object[] {albumModels,genreModels}); // Fonksiyonun aldığı parametreler


...
...

Bu konuda başka bir örneğin bulunduğu linki aşağıda veriyorum. Yalnız bu linkteki örnekteki kodu kullanmak için method.setAccessible(true) kodunu eklemeniz gerekiyor, çünkü private method çalıştırmak için önce accessible yapmamız gerekiyor.

http://www.java2s.com/Tutorial/Java/0125__Reflection/Callaclassmethodwith2arguments.htm

Şimdilik bu kadar. Kafanıza takılan soruları yazarsanız beraber çözüm bulmaya çalışırız.

Herkese sevgiler, saygılar.

Java'da Junit ile Yazılım Testi

Arkadaşlar Merhabalar,

Birkaç haftadır yazı yazamıyorum. Bunun sebebi işyerinde bana verilen işlerin yoğunlaşmış olması. Bu hafta bir test projesi verildi bana. En son adamakıllı testi ÖSSde çözmüş olan ben :), test deyince kafamda birşey oluşmadı tabii. Ama bu bir haftadaki araştırmalarım gösterdi ki, testler yazılımlar için kritik bir rol oynuyorlar ve yazılmaları bazen test edeceğimiz koddan çok daha zor olabiliyor. Mesela ben 30-40 satır bir kod için yaklaşık 150 satır test kodu yazmak durumunda kaldım. Ama gözünüzü korkutmasın, bir öğrendiniz mi gerisi geliyor :)

Test için çeşitli kütüphaneler mevcut, ben Junit'i tercih ettim. Sitesinden son versiyonunu indirip projenizin "Build path" kısmına ekleyerek kullanmaya başlayabilirsiniz. Burada yardımcı olarak bir kütüphane daha kullanacağız, bu da Jmockit kütüphanesi. Kod kısmında bazen fonksiyonları kendi istediğimiz gibi yönlendirmemiz gerekebiliyor, mesela veritabanına bağlanarak veri çeken, ama testte veritabanına bağlanmadan verileri hazırlamak istediğimiz bir metodu test ederken, projenin DAO(Data Access Object) kısmında veriyi çeken metodu Mock ederek, yani bir şekilde Bypass diyebiliriz, bu işi halledebiliriz. Nasıl olacağını kod kısmında hepberaber görelim.

// Bu method test başlamadan önce çalışır, constructor ya da page_load fonksiyonları gibi düşünebiliriz
     @Before
    public void setUp() throws Exception {
        instance = new HafifmuzikDriverImpl();
    }
// Bu method da test bittikten sonra çalışır, veritabanı bağlantısını vb. kesebileceğiniz yerdir. Hata yakalamadaki finally kısmına benzer.
    @After
    public void tearDown() throws Exception {
    }

// Burada DataDriverImpl sınıfında bulunan mockDataDriverImpl fonksiyonunu Mock ediyoruz

                MockUp<DataDriverImpl> mockDataDriverImpl = new MockUp<DataDriverImpl>(){
            @Mock
            public String fillExportDataWith(){                                         return mockDataExportData;
            }
 // Bir sınıf için birden çok fonksiyonu mock edebiliyoruz
            @Mock
            public DataLogger getLogger() {
                return DataLoggerFactory.getLoggerInstance(this.getClass());
            }
        };
...
...
...
// Burada karşılaştırma işlemi yapılıyor, ilk parametre expected value, ikincisi actual value.
assertEquals("12486564", fillExportDataWith());

Kısaca test işlemi buydu. Burada zor olan kısım test işleminden ziyade Mock işlemleri bence. Daha detaylı bilgileri junitin ve jmockitin sitelerinden ve google'den öğrenebilirsiniz. Ayrıca aşağıdaki linkte de çok değerli ve geniş bilgiler bulunmaktadır.

http://erhan.kesken.org/2011/03/jmockit-ile-ideal-birim-test.html

Herkese kolay gelsin.

9 Ağustos 2011 Salı

Hibernate - Annotation ile One-to-Many Mapping - 2

Herkese Merhabalar,

Kısa bir konudan bahsedeceğim yine. Hibernatede One-to-One ilişkide iki tablo arasında kurulan bağlantının ayrı bir Join tablosunda tutulmasını gerçekleştiren annotationlarımız kısaca aşağıdaki gibidir. Belki birileriinni işine yarar :)

Driver.Java
@Entity
@Table(name="DRIVER")

public class Driver {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="ID")
    private int driverId;
   
    @OneToOne(cascade=CascadeType.ALL)
    @JoinTable(name="Driver_Vehicle",joinColumns={@JoinColumn(name="ID")},inverseJoinColumns={@JoinColumn(name="VID")})

    private Vehicle vehicle;

...
...
}
Vehicle.Java
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)

public abstract class Vehicle {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="VID")
    private int id;
...
...
}

One-to-Many için de benzer kodlar geçerlidir. List ve ArrayList kullanımında bir değişikliğe gerek yok iken, HashMap kullanımında @MapKeyColumn annotationu kullanımı işe yarayacaktır.

Herkese kolay gelsin.