25 Ağustos 2011 Perşembe
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.
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
// Burada DataDriverImpl sınıfında bulunan mockDataDriverImpl fonksiyonunu Mock ediyoruz
// Bir sınıf için birden çok fonksiyonu mock edebiliyoruz
@Mock
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.
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
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.
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;
@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.
8 Ağustos 2011 Pazartesi
Hibernate ile Abstract Sınıfı Veritabanına Kaydetme - 2
Herkese Merhabalar,
Bugün yine Hibernate frameworku ile devam ediyoruz. Bu seferki problem oldukça karışık, benim için anlatması sizin için anlaması zor olacak sanırım ama deneyeceğiz bakalım :)
Elimizde bir adet abstract sınıf var, 2 tane de bundan türeyen POJO sınıf, bir tane de bu abstract sınıfla has-a-relation bağlantısı olan Java sınıfı. Şöyle düşünebilirsiniz, son bahsettiğim java sınıfı bir sürücü. Bir sürücü çeşitli araçlar sürebilir, traktör, kamyon vs. İşte bu sürdüğü arabayı temsilen içinde bir abstract sınıf var, taşıt oluyor bu da. 2 adet POJO sınıfımız da taşıt türleri oluyor, otobüs ve kamyon atıyorum. Bunlar abstract sınıfı extend ediyor daha önce dediğim gibi. Böylelikle bütün sürücüler için sürdüğü aracın türünü belirtmeden esnek bir şekilde tutabiliyoruz. Bun OOP olarak gerçekleştirmekte bir sorun yok ama, Hibernate ile veritabanına kaydedecekken biraz sorun çıkabiliyor. Bu da aslında daha önceki yazımda bahsettiğim @MappedSuperClass annotationu ile denemem sonucu oluştu sanırım. @MappedSuperClass annotationu verdiğimiz bir sınıfı başka bir sınıf içerisinde has-a-relation ilişkisiyle bulundurduğumuz zaman bir sorun çıkıyor. Burada bu annotationu @Entity ile değiştirmemiz gerekiyor. Aşağıda basitçe yazacağım kullanmamız gereken annotationları, umarım faydalı olur.
Bus.Java
Truck.Java
@Entity
@Table(name="TRUCK")
public class Truck extends Vehicle{
...
}
Driver.Java
@Entity
@Table(name="DRIVER")
public class Driver {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ID")
private int driverId;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="Vehicle_Id")
private Vehicle vehicle;
...
}
Vehicle.Java
Kafanıza takılan sorular olursa çekinmeden sorabilirsiniz. Herkese kolay gelsin.
Bugün yine Hibernate frameworku ile devam ediyoruz. Bu seferki problem oldukça karışık, benim için anlatması sizin için anlaması zor olacak sanırım ama deneyeceğiz bakalım :)
Elimizde bir adet abstract sınıf var, 2 tane de bundan türeyen POJO sınıf, bir tane de bu abstract sınıfla has-a-relation bağlantısı olan Java sınıfı. Şöyle düşünebilirsiniz, son bahsettiğim java sınıfı bir sürücü. Bir sürücü çeşitli araçlar sürebilir, traktör, kamyon vs. İşte bu sürdüğü arabayı temsilen içinde bir abstract sınıf var, taşıt oluyor bu da. 2 adet POJO sınıfımız da taşıt türleri oluyor, otobüs ve kamyon atıyorum. Bunlar abstract sınıfı extend ediyor daha önce dediğim gibi. Böylelikle bütün sürücüler için sürdüğü aracın türünü belirtmeden esnek bir şekilde tutabiliyoruz. Bun OOP olarak gerçekleştirmekte bir sorun yok ama, Hibernate ile veritabanına kaydedecekken biraz sorun çıkabiliyor. Bu da aslında daha önceki yazımda bahsettiğim @MappedSuperClass annotationu ile denemem sonucu oluştu sanırım. @MappedSuperClass annotationu verdiğimiz bir sınıfı başka bir sınıf içerisinde has-a-relation ilişkisiyle bulundurduğumuz zaman bir sorun çıkıyor. Burada bu annotationu @Entity ile değiştirmemiz gerekiyor. Aşağıda basitçe yazacağım kullanmamız gereken annotationları, umarım faydalı olur.
Bus.Java
@Entity
@Table(name="BUS")
public class Bus extends Vehicle{
@Table(name="BUS")
public class Bus extends Vehicle{
...
}Truck.Java
@Entity
@Table(name="TRUCK")
public class Truck extends Vehicle{
...
}
Driver.Java
@Entity
@Table(name="DRIVER")
public class Driver {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ID")
private int driverId;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="Vehicle_Id")
private Vehicle vehicle;
...
}
Vehicle.Java
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Vehicle {
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Vehicle {
...
}Kafanıza takılan sorular olursa çekinmeden sorabilirsiniz. Herkese kolay gelsin.
5 Ağustos 2011 Cuma
Hibernate ile Abstract Sınıfı Veritabanına Kaydetme
Arkadaşlar Merhabalar,
Bugün size çok kısa ve yararlı bir bilgi vereceğim. Hibernate ile uğraşırken karşıma şu sorun çıktı, elimde 3 tane sınıf ve 1 tane abstract sınıf var. 3 sınıf da bu abstract sınıfı extend ediyor ve veritabanına kaydederken, bu sınıfların türüne göre kaydetmesini istiyorum. Örneğin,
AbstractClass a = new Class1();
session.save(a);
ise veritabanında Class1'in tablosuna kaydetmesini, Class2 ise başka bir tabloya kaydetmesini istiyorum. Bunun için, abstract sınıfın başındaki @Entity annotationunu silip aşağıdaki annotationu yazarız.
@MappedSuperclass
Böylelikle amacımıza ulaşmış olacağız. Umarım faydalı olur. Herkese kolay gelsin.
Bugün size çok kısa ve yararlı bir bilgi vereceğim. Hibernate ile uğraşırken karşıma şu sorun çıktı, elimde 3 tane sınıf ve 1 tane abstract sınıf var. 3 sınıf da bu abstract sınıfı extend ediyor ve veritabanına kaydederken, bu sınıfların türüne göre kaydetmesini istiyorum. Örneğin,
AbstractClass a = new Class1();
session.save(a);
ise veritabanında Class1'in tablosuna kaydetmesini, Class2 ise başka bir tabloya kaydetmesini istiyorum. Bunun için, abstract sınıfın başındaki @Entity annotationunu silip aşağıdaki annotationu yazarız.
@MappedSuperclass
Böylelikle amacımıza ulaşmış olacağız. Umarım faydalı olur. Herkese kolay gelsin.
4 Ağustos 2011 Perşembe
Hibernate için İnternetteki Faydalı Linkler
Merhabalar,
Sizlerle internette bulduğum Hibernate ile alakalı faydalı linkleri paylaşmak istiyorum. Hem sizler faydalanmış olursunuz, hem de ben unutmamış olurum :)
- http://www.vaannila.com/index.html (Hibernate dahil birçok öğrenilmesi gereken konuları çok güzel bir şekilde anlatmış)
- http://www.roseindia.net/hibernate/
- Ve tabii ki.. http://www.hibernate.org (Siteen indirebileceğiniz user manual'i dikkatle okumanızı tavsiye ederim, böylelikle ezbere gitmektense öğrenerek ilerlemiş olursunuz)
- http://www.hiberbook.com/
Aklıma geldikçe bu listeyi kabartacağım :) Herkese kolay gelsin.
Sizlerle internette bulduğum Hibernate ile alakalı faydalı linkleri paylaşmak istiyorum. Hem sizler faydalanmış olursunuz, hem de ben unutmamış olurum :)
- http://www.vaannila.com/index.html (Hibernate dahil birçok öğrenilmesi gereken konuları çok güzel bir şekilde anlatmış)
- http://www.roseindia.net/hibernate/
- Ve tabii ki.. http://www.hibernate.org (Siteen indirebileceğiniz user manual'i dikkatle okumanızı tavsiye ederim, böylelikle ezbere gitmektense öğrenerek ilerlemiş olursunuz)
- http://www.hiberbook.com/
Aklıma geldikçe bu listeyi kabartacağım :) Herkese kolay gelsin.
Kaydol:
Kayıtlar (Atom)