Testcontainers ile RabbitMQ için Integration Test

Mustafa Daşgın
Trendyol Tech
Published in
4 min readApr 29, 2019

Test Driven Development (TDD) pratiğinin ekibe ve projeye kattığı faydalar bir çok yazılım geliştirici tarafından bilinir durumda. Biz de Trendyol Tech olarak TDD pratiğini Unit, Integration hatta Contract testlerimizde yoğun bir şekilde uyguluyoruz.

Aynı zamanda işe alım süreçlerimizde, birlikte çalışmak istediğimiz yazılımcılarla, bu pratiği ne kadar özümsedikleri ve projelerini geliştirirken ne derinlikte kullandıklarını anlayabilmek için basit case çalışmaları yapıyoruz. Genel olarak adaylardan gözlediğimiz TDD’nin teori olarak bilindiği ve az da olsa uygulanılmaya çalışıldığı..

Bunun yanında TDD’yi neden uygulamıyorsunuz sorusuna aldığımız cevaplar genelde zaman baskısı, yönetici baskısı, vb. sebepler oluyor. TDD pratiğinin özümsenmesi ve uygulanması, öğrenme sürecinde belli bir disiplin gerektirdiği için ufak bir dirençte ilk refleks pratikten vazgeçmek oluyor. Benim düşüncem ise baskı altında Agile, TDD, Pair programming gibi süreç ve pratiklerden uzaklaşmak yerine, yazılan kodu güvenceye alacak bu araçlara daha da sıkı sarılınmalı. TDD’nin felsefesi ve doğru şekilde uygulanması başka bir muhabbetin konusu.

Test Piramidi

Projenizde test kaynağınızın iyi organize edilmesi, uygulanan testlerin sayıca olması gereken dağılımını gösteren bir test piramidi yapısı vardır.

Bu geleneksel piramide göre projeniz en fazla Unit Testler, sonra Integration Testler sonra da EndToEnd ve Manuel testler ile teste tabi tutulmalıdır. Eğer firmanızda yazılan testleri piramit yerine huni şeklinde uyguluyorsanız yani yapılan Manuel testlerinizin sayısı diğer testlerin sayısından fazla ise kaynak kullanımınızda bir problem var demektir. Yapılan testleri otomatik çalışır hale getirmeli ve piramidi sağlamalısınız.

Microservice dünyasında ise işler biraz değişiyor. İşlevsel olarak küçük, sadece bir işin sorumluluğunu alan servisler büyük resmi oluşturabilmek için hem birbirleriyle hem de kuyruk, repository katmanı gibi yapılar ile entegre halde çalışmak zorundalar. Haliyle test piramidimiz kendini balpeteği formuna dönüştürüyor. Yani iş mantığını test eden Unit Testler sayıca azalırken, entegrasyonu sağlayan kodların test sayıları artıyor.

Trendyol’da integration testlerimizi yazarken hayatımızı kolaylaştıran bir kaç tane framework kullanıyoruz. Integration test diyebileceğimiz fakat iki microservice arasındaki rest iletişimi test eden daha özelleşmiş Contract testler için Pact.io, özellikle diğer microservice bağımlılıklarının testini yönetmek için WireMock ve RabbitMQ, Couchbase, DB, vb. entegrasyonlarımızı gerçekleştiren kod parçacıklarımız için de Testcontainers frameworklerini kullanıyoruz.

Bu yazımızda da Testcontainers ile bir RabbirMQ bağlantısını nasıl test ettiğimizi anlatacağız.

Testcontainer Hakkında

Testcontainer framework’ünü basitçe, test aşamasında, verilen Docker Image bilgilerine göre ortamda Docker container ayağa kaldırıp testlerimize başlamamıza olanak sağlayan bir araç olarak niteleyebiliriz.

Framework’ün kütüphanesinde DB, Couchbase, InfluxDB, Elasticsearch, Kafka vb. farklı bileşenlerin testleri için önceden hazırlanmış ve hale eklenmeye devam eden componentler barındırmakla birlikte docker image name ve version vererek de kendimiz container ayağa kaldırabiliyoruz.

DeliveryListener için Integration Test Sınıfı

RabbitMQ için önceden hazırlanmış bir sınıf olmadığı için Spring Boot kullanarak RabbitMQ testi için Test sınıfımızda şöyle bir tanım ve hazırlık yapmamız gerekiyor:

Hızlıca özetlemek gerekirse Delivery ile ilgili bir eventin Listener sınıfımızdan kuyruğa bırakıldığında dinlendiğini test edeceğimiz bir senaryoda test sınıfımızda bir rabbitMq instance’ı kaldırıp ona mesaj göndereceğiz ve Listener sınıfımız tarafından dinlenildiğini teyit edeceğiz. Yukarıdaki test kodu parçacığında bu amaçla bir rabbitMQ instance’ını TestContainer ile ayağa kaldırıyoruz. Burada dikkat etmemiz gereken nokta Testcontainer’ın @ClassRule annotation’ı ile tanımlanması ve test sınıfının farklı bir Initializer’a sahip olması. Ayrıca testlere başlayabilmek için sunucunun ayağa kalktığından waitingFor() methodunu kullanarak emin oluyoruz.

Sonraki aşamada Spring Context’i ayağa kakmadan önce Testcontainer’ın bizim için ayağa kaldırdığı RabbitMQ sunucu bilgilerini kullanacağımız property değerlerine geçiyoruz.

Kod parçasının son bölümünde ise rabbitMQ’ya test mesajı gönderebilmek için sadece bu test içinde kullanacağımız RabbitTemplate tanımını yapıyoruz.

Test methodumuz

Asıl testimizi yapacak test metodumuza geldi sıra:

Burada da DeliveryListener sınıfımız içinde çağıralacak UpdateOrderStatusService’i mocklayarak uygun parametreler ile çağırıldığın kontrolünü yaptık. Sıra geldi asıl işi yapacak sınıfı, DeliveryListener sınıfını yazmaya:

DeliveryListener

Böylelikle Testcontainer frameworku sayesinde testlerin çalıştığı herhangi bir ortamda RabbitMQ kurulu olmasına gerek kalmadan, ihtiyaç duyduğumuz Integration Test’i yazabildik. İlk çalışmada eğer ayağa kaldırmak istediğiniz RabbitMQ’nun Docker image’ı ortamınızda yoksa testin çalışmaya başlaması biraz zaman alacaktır. Sonraki testler sorunsuz ve hızlı bir şekilde çalışıp sonlanıyor.

Benzer bir şekilde Couchbase için Testcontainer kullanma ihtiyacınız olursa örnek koda şuradan erişebilirsiniz.

Eğer Trendyol Tech ekibi ile tanışmak, neler yapıyoruz konuşmak, projelerinden bize de bahsetmek istersen #cometotrendyol ya da insankaynaklari@trendyol.com

söz uçar yazı kalır..

--

--