spock mocking stubbing
Spock ile Alay Etme, Stubbing ve Casusluk:
Spock Çerçevesinde Parametreli Test bu detaylı olarak açıklandı Spock'ta Eğitim Dersleri Dizisi .
Alay ve Stubbing, kapsamlı Birim testlerinin en temel yapı taşlarından biridir. Alay etme ve alay etme desteği, bir çerçeve için pastadaki kiraz gibidir.
JUnit, JBehave, vb. Gibi mevcut çerçeveler için taklitler ve taslaklar için destek kutudan çıkmaz, bu nedenle bir geliştiricinin Mockito, PowerMock, EasyMock vb. Gibi üçüncü taraf kitaplıklarını kullanması gerekir. birim testleri.
Taklitleri ve taslakları ve bunların kullanım durumlarını anlamak için Serimize göz atabilirsiniz. Mockito öğreticisi .
Bu eğitimde, Spock kütüphanesine entegre edilmiş olan dahili Mocking ve Stubbing özellikleri hakkında daha fazla bilgi edineceğiz, bu da daha kolay Groovy sözdizimini kullanmayı sağlayacak ve böylece diğer 3'ü ekleme / dahil etme ihtiyacını azaltacakrdparti kütüphaneleri.
Tüm geçerli Java kodları da geçerli Groovy kodu olduğundan, testlerinize her zaman diğer Mocking çerçevelerini dahil edebilirsiniz.
Ne öğreneceksin:
- Test Edilen Uygulama
- Spock'ta alay etmek
- Spock'ta Stubbing
- Spock'ta casusluk
- Sonuç
- Uygulama için kaynak kodu
- Önerilen Kaynaklar
Test Edilen Uygulama
Öncelikle, Spock çerçevesinde taklitler ve taslaklar kullanarak test edeceğimiz örnek bir Java Uygulaması tanımlayalım.
Belirli bir Öğrenci Kimliği için soyutlanmış bir veritabanından toplam puanı alan ve toplam puanın değerine bağlı olarak basit bir not verme mantığına sahip bir StudentGradeCalculator Uygulaması üzerinde çalışacağız. Öğrenci puanlarını ve notlarını almak ve güncellemek için birkaç yöntemi olan bir veritabanı arayüzü kullanacağız.
Uygulama kodu, bu eğitimin son bölümünde mevcut olacaktır.
Spock'ta alay etmek
Video öğretici
Bu bölümde, Spock çerçevesinde Mocks'ın nasıl başlatılacağını ve başlatılacağını ve sahte üzerinde etkileşimlerin nasıl doğrulanacağını, yani test edilen yöntemin beklentilerine göre gerçekleşen sahte çağrıların doğrulanmasını göreceğiz.
Mocks ile çok fazla kurulum yapmanız gerekmez, ancak test edilen uygulamaya sağlanan sahte nesnelerle gerçekleşen etkileşimleri doğrulayabilirsiniz.
Taklitlerle şu gibi şeyler yapabilirsiniz:
- Taklitlere hangi argümanlar çağrıldı?
- Toplam çağrı sayısı vb. Neydi?
- Taklitlerin sırasını tespit etmek.
Alay edilen veritabanı uygulama nesnesini sağladığımız ve Mock ile etkileşimleri doğruladığımız, StudentGradeCalculator'ın basit bir örneğini görelim. Basit örneklerle alaycı özellikleri anlamaya çalışacağız.
Lütfen tüm etkileşim doğrulamalarının kurallara göre 'o zaman' bloğunda gerçekleşmesi gerektiğini unutmayın.
şelale yazılım geliştirme yaşam döngüsü modelleri
Test edilen yöntemin kodu aşağıdadır (' ne zaman: 'Blok)
public String calculateStudentGrade(String studentId) { String grade; // check if grade is already there in database grade = studentDatabase.getStudentGrade(studentId); if(grade!=null && !grade.isEmpty()) { return grade; } List scoreList = studentDatabase.getStudentScores(studentId); Float totalScore = 0F; if(scoreList !=null) totalScore = scoreList.stream().reduce(0F,(a,b)->a+b); if(totalScore > 90) { grade = 'A'; } else if (totalScore > 80) { grade = 'B'; } else { grade = 'C'; } // update the calculated grade in database studentDatabase.updateStudentGrade(studentId, grade); return grade; }
# 1) Etkileşimleri kesin bağımsız değişkenlerle doğrulama: İlk önce tam olarak beklenen bağımsız değişkenlerle etkileşimleri doğrulayalım. Burada, alay edilen yöntemlerin tam bağımsız değişkenlerle çağrılmasını bekleyeceğiz (yöntem yürütme akışına göre).
Buraya ' öğrenciDatabase ', Etkileşimleri doğruladığımız bir veritabanı arayüzünün Mock'udur.
def 'illustrate mocks for interaction verification with arguments'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.updateStudentGrade('123','C') 1*studentDatabase.getStudentGrade('123') }
Yukarıda gösterildiği gibi, alay edilen uygulamanın çağrılmış olması için kesin argümanlarla doğruluyoruz. Bu bağımsız değişkenlerde yapılacak herhangi bir değişiklik, testin başarısız olmasına neden olur ve hata günlüğü uygun nedeni gösterir.
Şimdi notu değiştirmeyi deneyelim ' updateStudentGrade 'C' yerine 'A' olarak adlandırılır ve test yürütüldüğünde hangi hatayı aldığımızı görün.
Too few invocations for: 1*studentDatabase.updateStudentGrade('123','A') (0 invocations) Unmatched invocations (ordered by similarity): 1 * studentDatabase.updateStudentGrade('123', 'C') 1 * studentDatabase.getStudentScores('123')
Sağlanan argümanlarla Mock çağrısını bulamadığı için 'Çok az çağrı' gibi bir hata gösterecektir.
bitişiklik listesi uygulaması c ++
#iki) Şimdi, gerçek argüman değerlerini sağlamadan Mock etkileşimlerini nasıl doğrulayacağımızı görelim, yani bizim ilgilendiğimiz şey, mock'un yöntemde çağrıldığını, ancak hangi argümanlarla değil.
Bu tür gereksinimler, esasen test edilen uygulamanın temel iş mantığına bağlı olan gerçek argümanları tanımlamak her zaman kolay olmadığından, gerçek üretim kodu için birim testleri yazarken en yaygın olanıdır.
Sözdizimi basittir, gerçek değerin bilinmediği bir bağımsız değişken için alt çizgi “_” kullanmanız yeterlidir.
Örneğin, herhangi bir String değerini kontrol etmek için, sadece '_ As String 'Testte bir bağımsız değişken yerine' ve herhangi bir String değeri için geçmelidir (diğer ilkel ve özel veri türleri için benzer şekilde).
Bunu bir Örnekle anlayalım
def 'illustrate mocks for interaction verification with generic matchers'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) 1*studentDatabase.getStudentGrade('123') }
Burada dikkat edilmesi gereken önemli bir nokta, hangi argümanların bilindiğini ve neyin bilinmediğini her zaman karıştırıp eşleştirebileceğinizdir. Örneğin, aşağıdaki örnekte, bir taklidin gerçek argümanlarla ve diğerinin gevşek eşleştiricilerle etkileşimini doğruluyoruz.
# 3) Son olarak, sahte çağrı sırasını, yani test yürütüldüğünde alayların hangi sırayla çağrıldığını belirleyebileceğimiz bir senaryo görelim.
Bazen, test edilen uygulamada birden fazla ortak çalışan / taklit olduğunda olayların akışını doğrulamak önemlidir ve yöntemlerin önceden belirlenmiş bir sırada çağrıldığını anlamak ve doğrulamak yararlıdır.
def 'illustrate mocks for validating order'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.getStudentGrade('123') then: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) }
Bu, basitçe Mock dizisi beklentileri sırasına göre birden çok 'o zaman:' bloğu kullanılarak gerçekleştirilebilir. Belirtilen sıra gerçek çağrı sırasını karşılamazsa, 'Yanlış çağrı sırası' ayrıntılarını içeren bir hata atılır.
Örneğin, yukarıdakilerin sırasını değiştirirsem sonra ifadeleri, test yürütmesi aşağıda gösterildiği gibi bir hata verecektir.
Wrong invocation order for: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) (1 invocation) Last invocation: studentDatabase.updateStudentGrade('123', 'C')
Spock'ta Stubbing
Video öğretici
Mocking hakkında her şeyi araştırdık, şimdi de alay edilen nesneler üzerinde Stub'ları nasıl tanımlayacağımızı görelim. Stubbing, test edilen uygulamanın farklı akışlarını / senaryolarını test etmek için Mock çağrılarında önceden tanımlanmış veya hazır yanıtlar oluşturmaktan başka bir şey değildir.
Bunu, çağrıldığında önceden tanımlanmış bir değeri döndürmek için bir sahte programlama olarak düşünün. Aynı StudentGradeCalculator uygulamasıyla devam edeceğiz ve farklı senaryoları test etmek için veritabanı arayüzü çağrılarını saplayacağız.
Saplama, bir bakıma gerçek nesnenin davranışını taklit eden bir Taklit gibidir. Bunu basitçe programlanmış bir Mock olarak adlandırabilirsiniz.
Stubbing Sözdizimi
Saplama için sözdizimi 2 sağa kaydırma operatöründen oluşur - ör. ' >> '
Herhangi bir aramaya bir saplama ayarlamak için, aşağıdaki şekilde tanımlayabilirsiniz:
StubbedObject.StubbedMethod(//argumentList) >> “Stubbed Response”
Şimdi Örnekler ile farklı saplama senaryolarını anlayalım.
# 1) Gerçek parametrelerle saplama: Argümanlar önceden biliniyorsa veya yalnızca çağrı belirtilen argümanlarla yapıldığında saplama ayarlamak istiyorsanız, bu şekilde stub belirtme yöntemi kullanılabilir.
def 'illustrate stubs with exact matchers'() { given: studentDatabase.getStudentScores('123') >> (20F, 30F, 50F) when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'A' }
Burada, saplamanın tam bir bağımsız değişkenle ayarlandığını görebilirsiniz, yani bu durumda StudentId '123' (başka herhangi bir değer için saplama çağrılmayacak ve varsayılan bir yanıt döndürülecektir).
# 2) Esnek eşleştiricilerle stubing: Argümanlar bilinmiyorsa (veya önemli değillerse), taklitler için yaptığımız gibi bunlardan gevşek bir şekilde bahsedebiliriz ve sözdizimi aynı kalır, yani alt çizgi “_”.
def 'illustrate stubs with loose matchers'() { given: studentDatabase.getStudentScores(_ as String) >> (20F, 30F, 10F) when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'C' }
# 3) Bir istisna atmak için saplama oluşturduğumuz başka bir hızlı örneğe bakalım.
Bu senaryolar, test edilen bir uygulamanın hata işleme mantığını doğrulamak için çok kullanışlıdır (gerçek dünyada olduğu gibi, tüm istisnaları oluşturmak aslında mümkün değildir, ancak istediğimiz istisnayı döndürmek ve sonra bunu ileri sürmek için basit bir saplama kurulabilir. sonra blok).
en iyi sanal gerçeklik uygulaması nedir
def 'illustrate stubs with exceptions thrown'() { given: studentDatabase.getStudentScores(_ as String) >> {throw new RuntimeException()} when: studentReportGenerator.calculateStudentGrade('123') then: thrown(RuntimeException.class) }
Spock'ta casusluk
Casuslar gerçek nesnelere dayanır yani soyut arayüzün kendisine değil arayüz uygulamasına ihtiyaçları vardır. Casuslar güçlüdür ve test edilen uygulama için çağrılan gerçek yöntemleri elde etmenize ve yöntemlerin hangi argümanlar için çağrıldığını doğrulamanıza izin verebilirler.
Casuslar, casusluk nesnesi örneklerine kısmi taklitler tanımlamaya da izin verir. yani, nesnede bazı yöntemlerin davranışını tanımlamak istediğinizi varsayalım, o zaman geri kalanının gerçek yöntem çağrıları olarak çağrılmasına izin verebilirsiniz.
Bunlar tipik olarak, uygulanmayan bazı arayüz yöntemlerinin olabileceği ve tamamen işlevsel olan birkaç başka arayüzün olduğu bir durumda yararlıdır. Bu nedenle, bir geliştirici olarak uygulanmayanları saplamayı seçebilir ve işlevsel yöntemlerin gerçek uygulamalarını çağırabilirsiniz.
Casus nesneler için saplamalar tanımlanmadıkça, varsayılan davranışın gerçek uygulamayı çağırmak olacağı unutulmamalıdır. Bunu söyledikten sonra, casuslar sık sık çağrılmamalı ve tüm senaryo kapsamı, taklitler, taslaklar ve bunların bir kombinasyonu kullanılarak gerçekleştirilebilir.
Aynı örneği kullanarak Spock çerçevesinde Spies kullanan birkaç örnek görelim. Öğrenci Notu Hesaplayıcı (Gerçek bir uygulama oluşturduk StudentDatabase kullanan bir bellek içi uygulama olan HashMap gerçek yöntemleri çağırmayı ve verileri döndürmeyi göstermek için. Kod, eğitimin son bölümünde mevcut olacaktır):
# 1) Saplama ve gerçek yöntem çağrılarının bir kombinasyonunu kullanarak casusluk yapmak
def 'illustrate spies'() { given: StudentDatabase spiedStudentDatabase = Spy(StudentDatabase.class) def studentReportGenerator = new StudentReportGenerator(spiedStudentDatabase) when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'A' 1*spiedStudentDatabase.getStudentGrade(_ as String) >> 'A' }
Yukarıdaki örnek, Spock çerçevesini kullanarak Spy oluşturmanın sözdizimini gösterir. Saplama, bildirim zamanının kendisinde tanımlanır.
Ayrıca, casusluk aramaları, blokta gösterildiği gibi doğrulanabilir (herhangi bir özel argüman için tanımlanabilen gevşek argüman eşleştiricilerle).
# 2) Tüm gerçek yöntem çağrılarını kullanarak casusluk yapmak
def 'illustrate spies with real method call'() { given: StudentDatabase spiedStudentDatabase = Spy(StudentDatabase.class) def studentReportGenerator = new StudentReportGenerator(spiedStudentDatabase) when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'C' 1*spiedStudentDatabase.getStudentGrade('123') }
Yukarıdaki örnekte, stubed herhangi bir davranıştan bahsetmediğimiz gibi, tüm çağrılar gerçek uygulamaya gidecektir.
Sonuç
Bu eğitimde, Spock çerçevesini kullanarak Mock Stub ve Spy için yerleşik teknikler hakkında her şeyi öğrendik. Spock, bu özellikleri çerçevenin bir parçası olarak daha okunaklı bir groovy sözdizimi ve daha az standart kodla birleştirerek işi kolaylaştırır.
Mocks, Stubs ve Casuslar, kapsamı artırmak ve test edilen uygulamanın temel iş mantığını test etmek veya doğrulamak için birim testlerinde yaygın olarak kullanılır.
Uygulama için kaynak kodu
StudentReportGenerator.java - bu, test edilen yöntem / uygulamadır
package app.studentScores; import java.util.List; public class StudentReportGenerator { public IStudentDatabase studentDatabase; public StudentReportGenerator(IStudentDatabase studentDatabase) { this.studentDatabase = studentDatabase; } public String calculateStudentGrade(String studentId) { String grade; // check if grade is already there in database grade = studentDatabase.getStudentGrade(studentId); if(grade!=null && !grade.isEmpty()) { return grade; } List scoreList = studentDatabase.getStudentScores(studentId); Float totalScore = 0F; if(scoreList !=null) totalScore = scoreList.stream().reduce(0F,(a,b)->a+b); if(totalScore > 90) { grade = 'A'; } else if (totalScore > 80) { grade = 'B'; } else { grade = 'C'; } // update the calculated grade in database studentDatabase.updateStudentGrade(studentId, grade); return grade; } }
IStudentDatabase.java - Veritabanı arayüzü
package app.studentScores; import java.util.List; public interface IStudentDatabase { List getStudentScores(String studentId); void updateStudentGrade(String studentId, String grade); String getStudentGrade(String studentId); }
StudentDatabase.java - IStudentDatabase.java arabiriminin InMemory uygulaması
package app.studentScores; import java.util.*; public class StudentDatabase implements IStudentDatabase { private Map scoreMap; private Map gradeMap; public StudentDatabase() { this.scoreMap = new HashMap(); this.gradeMap = new HashMap(); scoreMap.put('123', Arrays.asList(40F, 30F, 30F)); scoreMap.put('456', Arrays.asList(10F, 10F, 30F)); gradeMap.put('123', 'C'); gradeMap.put('456', 'A'); } @Override public List getStudentScores(String studentId) { return scoreMap.get(studentId); } @Override public void updateStudentGrade(String studentId, String grade) { gradeMap.put(studentId,grade); } @Override public String getStudentGrade(String studentId) { return gradeMap.get(studentId); } }
Yaklaşan eğitimimizde, Spock çerçevesini diğer test çerçeveleri ve teknolojileriyle nasıl entegre edeceğimizi göreceğiz.
PREV Eğitimi | SONRAKİ Eğitici
Önerilen Kaynaklar
- Spock Framework ile Birim Testleri Yazma
- Spock Mülakat Soruları ve Cevapları (En Popüler)
- Selenyum ile Entegrasyon ve Fonksiyonel Test İçin Spock
- Spock Framework ile Veriye Dayalı veya Parametreli Test
- Spock Eğitimi: Spock ve Groovy ile Test Etme
- En İyi ÜCRETSİZ C # Eğitim Serisi: Yeni Başlayanlar İçin En İyi C # Rehberi
- HP LoadRunner Öğreticileriyle Yük Testi
- Örneklerle C ++ 'da Tarih ve Saat İşlevleri