হ্যালো হাসিব! এটি আগের লেকচারের কন্টিনিউয়েশন। আগের লেকচারে আমরা AutoFixture-এর কনসেপ্ট শিখেছিলাম এবং একটিমাত্র টেস্ট মেথডে তা অ্যাপ্লাই করেছিলাম। এই লেকচারটিতে মূলত একটি অ্যাসাইনমেন্ট সল্যুশন দেখানো হয়েছে, যেখানে পুরো PersonsServiceTest ক্লাসের সব ইউনিট টেস্ট মেথডকে ম্যানুয়াল ডামি অবজেক্ট থেকে AutoFixture-এ কনভার্ট করা হয়েছে।
যেহেতু তুমি অলরেডি আগের লেকচার থেকে Create() এবং Build().With() এর কনসেপ্ট বুঝে গেছো, আমি শুধু এই লেকচারের ইম্পরট্যান্ট পয়েন্টগুলো (Takeaways) নিয়ে আলোচনা করছি।
📝 Lecture Summary at a Glance
- Full Refactoring:
PersonsServiceTestক্লাসের সব মেথড থেকেnew PersonAddRequest { ... }এর মতো হার্ডকোড করা ডামি অবজেক্ট সরিয়ে AutoFixture-এরCreateবাBuildমেথড বসানো হয়েছে। - Null Testing: যে টেস্ট মেথডগুলো শুধুমাত্র
nullইনপুট টেস্ট করে (যেমন:AddPerson_NullPerson), সেখানে AutoFixture ব্যবহার করার কোনো দরকার নেই। - Customizing Search Data: ফিল্টার বা সার্চ টেস্ট করার সময় (যেমন:
M-Aদিয়ে সার্চ করলেMaryবাRaymondআসবে), AutoFixture-কেWithমেথড দিয়ে স্পেসিফিক নাম সেট করে দিতে হয়, না হলে র্যান্ডম নামে সার্চ কাজ করবে না। - Maintaining Integrity: Foreign Key (যেমন
CountryId) এর ক্ষেত্রে, যে Country-টি ডাটাবেসে অ্যাড করা হয়েছে, ঠিক সেই ID-টিইPersonAddRequest-এWithমেথড দিয়ে বসিয়ে দেওয়া হয়েছে।
🧠 Comprehensive Breakdown & Deep Dive
১. Knowing When to Customize (Build vs Create) [Importance: 9/10]
- The “Why”: তুমি যদি এমন কোনো মেথড টেস্ট করো যেখানে নামের ফিল্টারিং বা সর্টিং লজিক নেই, সেখানে শুধু
_fixture.Create<T>()ব্যবহার করলেই হয়। কিন্তু ফিল্টার বা সর্ট টেস্ট করার জন্য তোমাকে জানতে হবে ডাটাতে কী আছে, তাই তখন কাস্টমাইজেশন মাস্ট।
💻 Code Implementation (Search Test):
// M-A স্ট্রিং দিয়ে সার্চ টেস্ট করার জন্য ডেটা সেটআপ
var personAddRequest1 = _fixture.Build<PersonAddRequest>()
.With(p => p.Email, "someone@example.com")
.With(p => p.PersonName, "Raymond") // M-A আছে
.With(p => p.CountryId, countryResponse.CountryId) // Foreign Key সিঙ্ক করা
.Create();
var personAddRequest2 = _fixture.Build<PersonAddRequest>()
.With(p => p.Email, "someone2@example.com")
.With(p => p.PersonName, "Mary") // M-A আছে
.Create();
২. Simplifying Repeated Code (DRY Principle) [Importance: 10/10]
- The “Why”: লেকচারার ভিডিওতে অনেকবার একই কোড (Country অ্যাড করা এবং ৩টা Person অ্যাড করা) কপি-পেস্ট করেছেন। ইউনিট টেস্টিংয়ে যদিও একটু কোড রিপিটেশন গ্রহণযোগ্য, কিন্তু ক্লিন আর্কিটেকচারে এটি একটি অ্যান্টি-প্যাটার্ন।
✅ Pro Tip (How to write Clean Tests): হাসিব, তুমি যখন রিয়েল প্রজেক্টে কাজ করবে, তখন এই রিপিটেড কোডগুলোকে ক্লাসের ভেতরে একটি প্রাইভেট Helper Method হিসেবে রেখে দেবে।
// Helper Method
private async Task<List<PersonResponse>> SeedDummyPersonsAsync(int count)
{
var country = _fixture.Create<CountryAddRequest>();
var countryResponse = await _countriesService.AddCountry(country);
var responses = new List<PersonResponse>();
for(int i = 0; i < count; i++)
{
var request = _fixture.Build<PersonAddRequest>()
.With(p => p.Email, $"test{i}@example.com")
.With(p => p.CountryId, countryResponse.CountryId)
.Create();
responses.Add(await _personsService.AddPerson(request));
}
return responses;
}
// Test Method এ জাস্ট এক লাইনে কল করবে!
[Fact]
public async Task GetAllPersons_ShouldReturnAllPersons()
{
// Arrange
var seededPersons = await SeedDummyPersonsAsync(3);
// Act
var actualResult = await _personsService.GetAllPersons();
// Assert
// ...
}
৩. Why Testing Null and Invalid Cases Matters [Importance: 8/10]
- The “Why”: যখন তুমি
UpdatePersonটেস্ট করছো ইনভ্যালিডPersonIdদিয়ে, তখন জাস্ট_fixture.Build<PersonUpdateRequest>().Create()কল করলেই কাজ হয়ে যায়। কারণ AutoFixture নিজে থেকে যে নতুনGuidজেনারেট করবে, সেটি ডাটাবেসে থাকা আগের কোনোPersonIdএর সাথে কখনোই মিলবে না! ফলে এটি অটোমেটিক্যালি একটি ইনভ্যালিড ID হিসেবে কাজ করবে এবং তোমার টেস্ট (যেটাArgumentExceptionথ্রো করার কথা) পাস হয়ে যাবে।
🚀 Summary of the Testing Stack
এখন পর্যন্ত তোমার টেস্টিং স্ট্যাকটি এরকম দাঁড়াচ্ছে:
- xUnit: মেইন টেস্ট রানার।
- Moq:
DbContextবা অন্য সার্ভিসকে ডামি (Mock) বানানোর জন্য। - AutoFixture: ডামি মডেল বা ডাটা জেনারেট করার জন্য।
পরবর্তী লেকচারে টেস্টিংয়ের আরেকটি দারুণ লাইব্রেরি FluentAssertions নিয়ে আলোচনা করা হবে, যা তোমার Assert স্টেটমেন্টগুলোকে অনেক বেশি রিডেবল এবং মানুষের ভাষার মতো করে তুলবে। তুমি রেডি হলে পরের ট্রান্সক্রিপ্টটি দিতে পারো!