{"id":16428512,"url":"https://github.com/buraksenyurt/event-driven-app-test","last_synced_at":"2026-04-27T18:33:21.632Z","repository":{"id":178057176,"uuid":"661305154","full_name":"buraksenyurt/event-driven-app-test","owner":"buraksenyurt","description":"Bu repoya konu olan çalışmadaki amaç .Net ile yazılmış ve event-driven yaklaşımını benimsemiş çözümlerde uçtan uca karmaşık testlerin nasıl yapılacağını anlamaya çalışmaktır.","archived":false,"fork":false,"pushed_at":"2023-08-06T18:35:55.000Z","size":12895,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-30T13:27:30.456Z","etag":null,"topics":["csharp","dotnet","dotnet7","entity-framework-core","event-driven-architecture","microservices","testing"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/buraksenyurt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-02T12:39:31.000Z","updated_at":"2023-07-18T09:34:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"1e3c35aa-666c-4e96-99ce-c98e6f1b0a72","html_url":"https://github.com/buraksenyurt/event-driven-app-test","commit_stats":null,"previous_names":["buraksenyurt/event-driven-app-test"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/buraksenyurt/event-driven-app-test","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buraksenyurt%2Fevent-driven-app-test","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buraksenyurt%2Fevent-driven-app-test/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buraksenyurt%2Fevent-driven-app-test/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buraksenyurt%2Fevent-driven-app-test/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/buraksenyurt","download_url":"https://codeload.github.com/buraksenyurt/event-driven-app-test/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buraksenyurt%2Fevent-driven-app-test/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32349645,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-27T17:12:42.749Z","status":"ssl_error","status_checked_at":"2026-04-27T17:12:41.658Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","dotnet","dotnet7","entity-framework-core","event-driven-architecture","microservices","testing"],"created_at":"2024-10-11T08:17:20.865Z","updated_at":"2026-04-27T18:33:21.597Z","avatar_url":"https://github.com/buraksenyurt.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Event-Driven Yaklaşımlı .Net Çözümlerinde Test Edilebilirlik\n\nBu repoya konu olan çalışmadaki amaç .Net ile yazılmış ve event-driven yaklaşımını benimsemiş çözümlerde uçtan uca karmaşık testlerin nasıl yapılacağını anlamaya çalışmaktır. Microservice yaklaşımını benimseyen dağıtık sistem çözümlerinde test edilebilirlik önemlidir. Sistemin parçalarının her an test edilebilir olması code coverage değerlerini yukarı çekip olası üretim hatalarının önüne geçmek için elzemdir. Repodaki çalışmada amaç öncelikle Event-Driven yaklaşıma uygun basit bir çözüm geliştirmek sonrasında test konusunu ele almaktır.\n\n## Senaryolar\n\nÇözüm içerisinde iki servis yer alıyor. EmployeeService ve InsuranceService. Her ikisi de basit birer REST servisi ve kendi SQLite veritabanlarına sahipler. InsuranceService içerisinde yer alan controller sınıfı, kontrat oluşturmak, güncellemek ve listelemek için üç fonksiyon içeriyor. EmployeeService içerisinde yer alan controller'da çalışan için satacağı poliçe sayısını hazırlamak, çalışan ve kontratları listelemek için üç fonksiyon içermekte. Yeni bir kontrat oluşturulması veya güncellenmesi EmployeeService için bir event anlamı taşımakta ve bu değişiklikler EmployeeService tarafından da değerlendirilmekte. Benzer durum sistemdeki bir sigortacı(çalışan) satışa çıkarken kullanacağı poliçileri sepetine aldığı zaman da geçerli. Bu durumda InsuranceService bundan haberdar olabilmeli ve kontrat miktarları buna göre revize edilmeli. \n\nServislerde gerçekleşen bazı eylemler sistem için bir olay(event) anlamına gelmekte. Bu noktada bir olayın muhatabının bu olayla ilgilenmesi için bir sisteme ihtiyaç var. RabbitMQ burada devreye giriyor. Servisler olaylarını asenkron olarak RabittMQ kuyruğuna bırakabiliyorlar. Olayın muhatapları bu aktiviteleri dinleyip kendi tarafları için gerekli eylemleri yapabiliyorlar. Bir servis tarafından üretilen bir nesnenin diğer servis tarafından da anlaşılabilmesi için ideal bir yapı. Dağıtık sistemlerde çok kullanılan bir çözüm.\n\n## RabbitMQ Hazırlıkları\n\nRabbitMQ'yu sistemde kolayca ayağa kaldırmak için DockerCompose dosyasından yararlanılabilir.\n\n```shell\nsudo docker-compose up\n```\n\nRabbitMQ sistemde ayağa kalktıktan sonra varsayılan olarak http://localhost:15672/#/ adresinden ulaşılabilir. Çözümde servisler arası haberleşmede bir exchange topic ve ayrılmış mesaj kuyrukları söz konusu.\n\nOluşturulan sales.exchange isimli exchange nesnesinin özellikleri şöyle olmalı.\n\n```text\nName : sales.exchange\nType : topic\nDurable : true,\nAutoDelete : false,\nInternal : false,\nArguments : null\n```\n\nBu exchange ile ilişkili olan kuyruklar ise aşağıdaki gibi oluşturulmalı.\n\n```text\nName : insurance.employee\nType : classic\nVHost: /\nAutoDelete : false\nDurable : true\n\nName : insurance.contract\nType : classic\nVHost: /\nAutoDelete : false\nDurable : true\n```\n\nOluşturulan bu mesaj kuyruklarının ilgili exchange'e bağlanması da gerekir. Aşağıdaki ekran görüntüleri setup konusunda fikir verebilir.\n\n![assets/rabbitmq_01.png](assets/rabbitmq_01.png)\n\n![assets/rabbitmq_02.png](assets/rabbitmq_02.png)\n\n![assets/rabbitmq_03.png](assets/rabbitmq_03.png)\n\n### RabbitMQ Çalışırlığının Kontrolü\n\nEğer işler yolunda gittiyse örnek bir Contract oluşturma talebine karşılık RabbitMQ tarafındaki ilgili mesaj kuyruğunda bir hareket olması gerekir.\n\nÖrneğin InsuranceService ayağa kaldırıldıktan sonra yeni bir sigorta sözleşme tipini sisteme eklemek istediğimizde aşağıdaki gibi bir talep kullanabiliriz.\n\n```bash\ncurl -X 'POST' \\\n  'http://localhost:5011/Contract' \\\n  -H 'accept: text/plain' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n  \"contractId\": \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n  \"title\": \"Bireyse Sağlık Sigortası Tip A\",\n  \"quantity\": 10\n}'\n```\n\nBuna karşın RabbitMQ tarafında şöyle bir şeyler görebiliyor olmamız gerekir.\n\n![assets/rabbitmq_04.png](assets/rabbitmq_04.png)\n\n![assets/rabbitmq_05.png](assets/rabbitmq_05.png)\n\n## Gün Doğumu Testi\n\nInsuranceService'teki CreateContract servis çağrımı ile yeni bir poliçe sisteme girildiğinde RabbitMQ tarafındaki insurance.contract kuyruğuna yeni eklenen veri bilgisini içeren bir mesaj bırakılır. EmployeeService ayaktaysa eğer, background task olarak çalışan servis insurance.contract kuyruğuna gelen mesajı yakalar. Mesaj içeriğinde gelen JSON tabanlı Contract içeriğini değerlendirir. ContractId bilgisini kullanarak kendi veritabanında _(EmployeeService.db)_ böyle bir poliçe olup olmadığına bakar. Eğer varsa kendi veritabanındaki poliçe bilgilerini günceller, yoksa yeni bir poliçe olarak ekler.\n\nBu ilk çalışma zamanı testini gerçekleştirmek için EmployeeService ve InsuranceService uygulamaları ayrı ayrı başlatılır. RabbitMQ arabirimine de http://localhost:15672 adresinden erişilir olduğundan emin olmak gerekir. İlk gün denemesinde insurance.contract isimli kuyruğa akan mesajlar yakalanır. Örneğin aşağıdaki ekran görüntüsünde olduğu gibi InsuranceService üstünden yeni bir Contract oluşturulduğunda, EmployeeService uygulaması buna ilişkin üretilen olayı dinlediği mesaj kuyruğundan yakalar, gerekli EF komutlarını işletir.\n\n![assets/rabbitmq_06.png](assets/rabbitmq_06.png)\n\nve hatta bu otomatik gerçekleşen dinleme işlemi sonrası EmployeeService üstünden poliçe bilgileri istendiğinde aşağıdaki gibi yeni gelen poliçenin kendi veritabanına eklendiği gözlemlenir.\n\n![assets/rabbitmq_07.png](assets/rabbitmq_07.png)\n\n## İkinci Gün Testi\n\nEmployeeService'indeki Post fonksiyonunu kullanarak var olan bir poliçenin miktarını değiştirdiğimizde buna bağlı olarak Insurance tarafındaki sözleşmenin de miktarı değiştirilir. Yani EmployeeService bir olay ile InsuranceService'i uyarırken tam tersi yönde bir mesaj yayını da söz konusudur. Örneğin EmployeeService üzerinden aşağıdaki gibi bir çağrım gerçekleştirdiğimizde,\n\n![assets/rabbitmq_08.png](assets/rabbitmq_08.png)\n\nInsuranceService tarafında aşağıdaki hareketler gerçekleşir.\n\n![assets/rabbitmq_09.png](assets/rabbitmq_09.png)\n\nYani InsuranceService kendi tarafındaki ilgili Contract verisinin Quantity değerini günceller. Nitekim EmployeeService, bir çalışanını ilgili poliçe'den belli miktarda sattığına/aldığına dair bir olay bildirimi yapmıştır. EmployeeService tarafında ise aşağıdaki gibi bir çalışma zamanı gerçekleşir.\n\n![assets/rabbitmq_10.png](assets/rabbitmq_10.png)\n\nBuna göre InsuranceService'te kendi tarafını güncelledikten sonra tekrar bu sözleşme bilgisine istinaden bir güncelleme olduğunu duyurur. Bu olay EmployeeService tarafından dinlendiği için EmployeeService kendi tarafındaki Contract tablosunda güncellemeye gider.\n\n## Web App Tarafı için Proxy Sınıflarının Üretilmesi\n\nEğitimde önyüz tarafındaki uygulamalar birer MVC projesi şeklinde oluşturulmakta. MVC projelerindeki Controller sınıflarının otomatik üretimi için Swagger şemasından yararlanabilen NSwag isimli CLI aracı kullanılmakta. Öncelikle bu aracın sistem yüklenmesi gerekiyor.\n\n```bash\ndotnet tool install --global NSwag.ConsoleCore\n\n# sonrasında InsuranceService çalıştırılıp swagger dokümanı json formatında çekilmelidir\n# Bu çalışma için örneğin http://localhost:5011/swagger/v1/swagger.json adresindeki içerik alınıp\n# Insurance.WebApp projesindeki ApiProxy klasörüne kaydedilir.\n# Sonrasında aşağıdaki komutlarla proxy sınıfının üretilmesi sağlanır. (Komut ApiProxy altında işletilmiştir)\nnswag openapi2csclient /input:swagger.json /classname:InsuranceApiClient /namespace:Insurance.WebApp /output:InsuranceApiClient.cs\n```\n\n![assets/rabbitmq_11.png](assets/rabbitmq_11.png)\n\nBurada yapılanları bir nevi Add Web Reference veya Add Service Reference işlemlerine benzetebiliriz. Insurance.WebApp projesindeki ApiProxy klasöründe otomatik olarak üretilen proxy sınıfı haricinde bunun kullanımını kolaylaştırmak üzere soyutlayan ve DI mekanizmasına kolayca monte edilmesini sağlayan yardımcı bir sınıfta vardır. IInsurancaApiHandler arayüzünü implemente eden InsuranceApiHandler sınıfı.\n\nİkinci web uygulaması ise çalışanların satış için kullandığı portföy bilgilerini yöneten bir program olarak tasarlanmaktadır. Temelde bir çalışan, satışa çıkmadan önce portföyüne belli miktarda poliçe alır. Bu işlerin görsel olarak yapıldığı uygulama olarak düşünebiliriz. Tabii bir önceki web uygulaması için geçerli olan işlemler bu uygulama içinde benzerdir. Employee.WebApp olarak isimlendireceğimiz mvc uygulaması da EmployeeService isimli api hizmetinin swagger üretimli proxy sınıfını kullanmaktadır. Dolayısıyla Insurance.WebApp uygulamasında olduğu gibi nswag aracı kullanılarak bu proxy sınıfının üretilmesi sağlanır.\n\nNot: ApiHandler görevi üstlenen enstrümanlar ve proxy sınıfları sonradan Common projesi altına alınmıştır. Güncel proxy sınıfı üretimleri için bu projedeki ApiClient/Employee ve ApiClient/Insurance klasörlerinde sırasıyla aşağıdaki komutlar işletilmiştir.\n\n```bash\nnswag openapi2csclient /input:swagger.json /classname:EmployeeApiClient /namespace:Common.ApiClient.Employee /output:EmployeeApiClient.cs\n\nnswag openapi2csclient /input:swagger.json /classname:InsuranceApiClient /namespace:Common.ApiClient.Insurance /output:InsuranceApiClient.cs\n```\n\n## Üçüncü Gün Testi\n\nŞu anda Insurance ve Employee tarafları için servis ve UI projeleri hazır durumda. UI üstünden poliçe girişi yapıp, bunu personele kullandırtabilir ve her iki uygulama tarafındaki verilerin nasıl değiştiğini inceleyebiliriz.\n\n![assets/day_3.gif](assets/day_3.gif)\n\n## Dördüncü Gün (Houston We Have a Problem)\n\nDördüncü gün testlerinde ubuntu sistemimde bir sorun yaşıyorum. Dockerize edilip docker-compose ile ayağa kaldırılan api servisleri aynı ağda olmalarına rağmen rabbitmq tarafına mesaj gönderemiyorlar. Yıldız tarihi 2023 itibariyle olayların gelişimi şöyle.\n\nApi ve WebApp'lar için birer dockerfile oluşturuldu. Bunlar docker-compose.yml dosyasında birleştirildi. RabbitMQ imajı da buraya alındı. Tüm servisler için bridge tipinden bir network tanımlandı. Ardından aşağıdaki komutlarla çalışmaya devam edildi.\n\n```bash\n# build işlemleri için\nsudo docker-compose build\n\n# docker container'larını ayağa kaldırmak içinse\nsudo docker-compose up\n```\n\nStandart olarak servis ve web adreslerine erişilebildiği görüldü. Ancak docker-compose loglarında şu hata mesajı ile karşılaştım.\n**Unhandled exception. RabbitMQ.Client.Exceptions.BrokerUnreachableException: None of the specified endpoints were reachable**\n\n![assets/day_4_1.gif](assets/day_4_1.gif)\n\nBunun üzerine appsettings dosya içeriklerini kontrol ettim. localhost yerine docker-compose dosyasında belirtilen rabbitmq-poc adını kullanmam gerektiğini biliyordum. Ancak yine de servisler rabbitmq sunucusuna erişememekteler. Aklıma network durumunu kontrol etmek geldi. Api servisleri, web uygulamaları ve rabbitmq aynı ağ içerisinde olmalıydılar. Aşağıdaki komutlarla devam ettim.\n\n```bash\n# önce network listesini taradım\nsudo docker network ls\n\n# sonra employee_mordor olarak oluşturulmuş ağı inceledim\nsudo docker network inspect 3ad\n```\n\n![assets/day_4_2.gif](assets/day_4_2.gif)\n\nAslında tüm servisler aynı ağa bağlanmış görünüyordu. Yine de servislerden rabbitmq tarafına mesaj gönderememekteyim. Bunu üzerine container'ların içerisine girip appsettings dosyalarını elle değiştirmeye ve network için atanan ip adresini kullanmaya karar verdim. Hatta insuranceapi ve employeeapi container'larından terminal açıp bu ip adreslerine telnet çekmeyi bile denedim.\n\n```bash\n# Tabii öncesinde container'ları bulmak lazım\nsudo docker ps -a\n\n# Örneğin insuranceapi isimli container içerisine bir terminal açmak için\n# şu komut kullanılabilir.\nsudo docker exec -it 5f1 bash\n\n# Tabii dosyaları düzenlemek için en azından nano gerekiyor.\n# Kullanılan imajlarda bu program hazır gelmediğinden install etmek gerekiyor.\napt-get update\napt-get install nano\n\n# Sonrasında ip bilgilerini rabbitmq'ya göre güncelledim.\n```\n\n![assets/day_4_3.gif](assets/day_4_3.gif)\n\nAncak sonuç değişmedi. Birkaç kez docker-compose içeriğini kaldırıp _(sudo docker-compose down)_ tekrardan ayağa kaldırsam da iletişim kurulmasını başaramadım. Sorunu henüz çözebilmiş değilim ancak eğitimin diğer modüllerine devam ediyorum. Eğitim asıl konusu olan test kısımlarında dockersız ilerleyebilirim. Diğer yandan hatayı çözemesemde birçok şey öğrendim. Docker-compose'da servisleri bir araya getirme, aynı ağa bağlama, ağın bilgilerini öğrenme, container içerisine terminal açma, terminalde nano ile dosya değiştirme vs \n\n~~Hiç yoktan iyidir.~~\n\n### Sorun Çözüldü\n\nBüyük ihtimalle o gece bu konu üzerine çok uğraştığım için hatayı gözden kaçırdım. Sorun RabbitMQ tarafındaki Exchange Topic ayarlaması ile ilgiliydi. Meğerse To kısmını yazmışken Routing Key kısımlarını boş bırakmışım.\n\n![assets/day_6_1.gif](assets/day_6_1.gif)\n\nBurayı doğru şekilde tanımladıktan sonra kuyrukların çalışmaya başladığını ve uygulamalar arası olayların tetiklenebildiğini gördüm.\n\n![assets/day_6_2.gif](assets/day_6_2.gif)\n\n## Kullanıcı Arayüz Testleri (UI Tests)\n\nUI Testleri için oluşturulan xunit tabanlı projeye [Playwright for .Net](https://playwright.dev/dotnet/) aracı eklenmiştir. Playwright ile web otomasyon testlerini yazmak mümkündür. Yani bir unit test fonksiyonundan tarayıcı açtırmak, belli bir adrese gitmek, alanları doldurmak, submit işlemlerini gerçekleştirmek, DOM nesne içeriklerini kontrol etmek vesaire gibi. Dolayısıyla örneğin Insurance.WebApp ya da Employee.WebApp projelerindeki UI testleri için manuel hareket etmek yerine kabul kriterlerini otomatize ettirebiliriz.\n\n```bash\n# Tabii sistemde Playwright'ın yüklü olması gerekiyor.\nnpx playwright install\n\n# xUnit tabanlı test projesini oluşturuyoruz\ndotnet new xunit -o Employee.Test.UI\n\n# Playwright paketini ekliyoruz\ndotnet add package Microsoft.Playwright\n\n# Ayrıca test kabul kriterleri için FluentAssertions paketi kullanılmaktadır\ndotnet add package FluentAssertions\n\n# Rastgele test verisi üretebilmek için AutoFixture paketinden yararlanılabilir\ndotnet add package AutoFixture\n\n# Testleri koşmak içinse\ndotnet test\n```\n\nÖrnekte yazılan ilk test metodu Insurance.WebApp uygulaması açıp Poliçe Oluştur sayfasına geliyor ve örnek bir poliçe bilgisi oluşturup submit ediyor. \n\n![assets/day_5.gif](assets/day_5.gif)\n\n## 6ncı Gün Durumu\n\nBugün arayüz(UI) testleri ile devam ettik. Unit test tarafında Theory ve InlineData attribute'larını kullanarak birden fazla veriden oluşan bir küme ile testleri çalıştırdık. Buna göre arka arkaya 3 test otomatik olarak yürütüldü. Sonuçlar aşağıdaki gibi oluştu. Dikkat edileceği üzere testler sonrasında web uygulamaların gittiğimizde poliçelerin geldiğini ve uygulamalar arasında tetiklenen olaylar ile miktarlarının taraflara yansıtılabildiğini görmekteyiz.\n\n![assets/day_6_3.gif](assets/day_6_3.gif)\n\nBu test modelinde şöyle bir sıkıntı vardır. Her çalıştırdığımızda aynı verilerin içeriye aktarıldığını görürüz. Aslında bazı hallerde sadece ekranlardaki kontrollerin dummy veri setleri ile çalıştığını görmek yeterlidir. Bu noktada rastgele veri üretimi için AutoFixture gibi paketlerden yararlanılabilir. Test projesine AutoFixture paketi eklendikten sonra sözleşme eklenmesi için kullanılan web uygulamasına rastgele title,quantity verilerinden oluşan içerikleri göndermemiz mümkündür.\n\n![assets/day_6_4.gif](assets/day_6_4.gif)\n\n## 7nci Gün Durumu\n\nBugün API testlerinin nasıl yazacağımızı öğrendik. Yine Playwright nuget paketinden yararlandık. Dikkat edilmesi gereken noktalardan birisi Deserialize operasyonları. Örneğin EmployeeApi'deki Contract Endpoint testinden gelen Json içeriğini List\u003cContract\u003e türüne çevirdikten sonra FirstOrDefault() fonksiyonları NullReferenceException'a sebebiyet verdi. Çünkü JSON içeriğindeki nitelik adlarının başharfleri büyük harfe çevirilmemekte. Bunun için JsonSerializerOptions eklenerek ilerlendi.\n\n![assets/day_7_1.gif](assets/day_7_1.gif)\n\n## Entegrasyon _(Integration)_ Testleri\n\nSenaryoda kendi web api'lerini kullanan ve birbirleriyle Rabbit MQ üstünden haberleşen iki web uygulaması söz konusu. Bir entegrasyon testi düşünüldüğünde genelde sistemin test edilmesi beklenen birçok noktası(checkpoint) olur. Sistemde veritabanları, web api'ler, web arayüzleri ve RabbitMq var. Çözümü çalıştırırken docker-compose dosyasını ayağa kaldırıyoruz. Böylece web api, ui ve rabbitmq için docker container'lar çalışır vaziyette oluyorlar. UI ve Api testlerinde bu container'ların ayakta olması gerekiyor. Entegrasyon testlerinde ise bunların ayakta olmadığı haliyle testler yazmaya çalışacağız. Örneğin SQLite veritabanını kullanmak yerine test çalışma zamanı kendi in-memory veritabanını kullanacak gibi.\n\n```shell\n# xUnit tabanlı test projesini oluşturuyoruz\ndotnet new xunit -o Integration.Test\n\n# Gerekli paketler\ndotnet add package Microsoft.AspNetCore.Mvc.Testing\ndotnet add package Microsoft.EntityFrameworkCore.InMemory\n\n# Ayrıca test kabul kriterleri için FluentAssertions paketi kullanılmaktadır\ndotnet add package FluentAssertions\n\n# Testleri koşmak içinse\ndotnet test\n```\n\n## 8nci Gün Testleri\n\nIntegration.Test projesindeki Should_Get_All_Contracts_From_InMemory_Works_Test test edilmek istendiğinde ilk etapta aşağıdaki gibi bir hata alınır.\n\n```text\nStarting test execution, please wait...\nA total of 1 test files matched the specified pattern.\ninfo: Microsoft.EntityFrameworkCore.Update[30100]\n      Saved 0 entities to in-memory store.\ninfo: Microsoft.EntityFrameworkCore.Update[30100]\n      Saved 1 entities to in-memory store.\nwarn: Common.Queue.RabbitMqService[0]\n      amqp://rabbitmq-poc:5672, rabbitmq-poc, -1\n[xUnit.net 00:00:01.69]     Integration.Test.EmployeeIntegrationTests.Should_Get_All_Contracts_From_InMemory_Works_Test [FAIL]\n  Failed Integration.Test.EmployeeIntegrationTests.Should_Get_All_Contracts_From_InMemory_Works_Test [618 ms]\n  Error Message:\n   RabbitMQ.Client.Exceptions.BrokerUnreachableException : None of the specified endpoints were reachable\n...\n```\n\nBu son derece doğal çünkü EmployeeService'e ait çalışma zamanının RabbitMQ bağımlılığı bulunuyor. Ancak RabbitMQ ve diğer api'ler ile web uygulamaları docker-compose'da belirtilen network üzerinden konuşuyorlar. Bu nedenle local ortamda RabbitMQ'yu çalıştırıp, EmployeeService web api uygulamasındaki konfigurasyon ayarlarındaki HostName bilgisini rabbitmq-poc'den localhost'a çekerek ilerlemek gerekiyor.\n\nBunun için proje düzeneğini biraz değiştirdim. IntegrationTest klasörüne farklı portlardan ayağa kalkacak bir RabbitMQ için docker-compose dosyası ekledim. 5672 yerine 5673 portunu kullanıyor. Dolayısıyla EmployeeService projesinin appSettings dosyasındaki host name bilgisini localhost, port bilgisini de 5673 yaparsak ilk entegrasyon testini şu an için ilerletebiliriz.\n\n![assets/day_8_1.gif](assets/day_8_1.gif)\n\n**EĞİTİMİM DEVAM EDİYOR. KONULARI İŞLEDİKÇE EKLEYECEĞİM.**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fburaksenyurt%2Fevent-driven-app-test","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fburaksenyurt%2Fevent-driven-app-test","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fburaksenyurt%2Fevent-driven-app-test/lists"}