Spring Boot / المتوسط: البيانات والأمان وأدلة الإطار / الدرس 10
شرائح الاختبار وحدود الدليل
اختر اختبار المجال و MVC والضبط والاستمرارية وفق ما يرصده فعلاً، بهويات واعتماديات مضبوطة.
في هذه الصفحة
أهداف الدرس
- تمييز النداء المباشر والشريحة والسياق.
- قراءة MockMvc و MockitoBean في الأساس المثبت.
- تجنب افتراض المستمع وتنظيف المعاملة.
اختر أضيق اختبار يرى الخطر
يرصد اختبار المجال الحساب ومتعاوناً صريحاً، وترصد شريحة الويب المسار والتحويل والنصيحة والمرشح المختار، ويرصد سياق الضبط الربط والشروط، ويرصد تكامل القاعدة التخزين والمعاملة. لكل سؤال مختلف؛ وقد تفوت مجموعة كبيرة الحد الذي يعتمد عليه الادعاء.
اشتق التأكيد من المتطلب لا اسم الحقل الخاص وفروع التنفيذ كلها. اختبر التالف والغائب والممنوع والتعارض مع النجاح، ببيانات صغيرة مصطنعة. سمّ السلوك وحد الدليل مثل«غياب المنتج يعيد 404 عبر MVC» لا «اختبار الخدمة» فقط، حتى يفسر الفشل الوعد الذي تغير.
افحص عقد ويب مقصوداً دون منفذ حقيقي
تحمل WebMvcTest شريحة المتحكم وتستورد سلسلة الأمان المقصودة. توفر MockitoBean من دعم 6.2 قدرة البحث، وتسمح سلطة مصطنعة بالقراءة. تلزم اعتماديات الاختبار والأمان المناسبة؛ ولم تنفذ الشيفرة هنا ولم يبدأ مستمع.
ترسل MockMvc عبر Servlet وهمية ولا تثبت مسار شبكة إنتاج. تفحص مرشحاً وتسلسلاً مختارين ولا تتحقق الهوية الوهمية من اعتماد حقيقي. أكد الحقول وأضف الغياب والمنع؛ ولا تعطل كل المرشحات للحصول على 200 إلا إذا صُرّح بأن السؤال يخص حداً أدنى مختلفاً.
package training.catalog;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebMvcTest(ProductController.class)
@Import(ApiSecurity.class)
class ProductControllerTest {
@Autowired MockMvc mvc;
@MockitoBean ProductService products;
@Test
@WithMockUser(authorities="catalog:read")
void knownProduct() throws Exception {
given(products.find(42L)).willReturn(Optional.of(new ProductView(42L,"Notebook")));
mvc.perform(get("/products/42"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(42))
.andExpect(jsonPath("$.name").value("Notebook"));
}
}
يحتاج العقود والاعتماديات المحددة؛ وتأكيداته مقصودة لا نتائج اختبار إطار مرصودة.
احصر اختبار الضبط في كائناته المقصودة
يمكن لـ ApplicationContextRunner إنشاء سياق صغير وفحص الكائن والربط أوفشل البدء المقصود. يستورد المثال ضبط الخصائص فقط ويقدم قيماً محدودة، ويحتاج اعتمادات الربط والتحقق إذا شُغل. لا يطلب تحميل إنتاج التطبيق أواتصالاته، وفحص الصياغة أضيق من تشغيله.
اختبر الغياب والمدى والملف والتجاوز المتعارض أيضاً. قد تهيئ SpringBootTest واسعة جدولة أوعميل أوبيانات لم يطلبها السؤال، فحدد النطاق. وليس النجاح لأن الضبط المطلوب لم يسجل أصلاً دليلاً على صحته؛ تحقق من وجود الحد الذي تريد اختباره.
package training.catalog;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
class CatalogConfigurationTest {
private final ApplicationContextRunner runner = new ApplicationContextRunner()
.withUserConfiguration(CatalogConfiguration.class);
@Test
void bindsKnownProperties() {
runner.withPropertyValues("catalog.max-page-size=20","catalog.timeout=2s")
.run(context -> {
assertThat(context).hasNotFailed();
assertThat(context).hasSingleBean(CatalogProperties.class);
assertThat(context.getBean(CatalogProperties.class).maxPageSize()).isEqualTo(20);
assertThat(context.getBean(CatalogProperties.class).timeout()).isEqualTo(Duration.ofSeconds(2));
});
}
}
يحدد التأكيد المقصود للضبط ولا يدعي تحديث سياق أو تشغيل تحقق.
اعرف متى يبدأ الاختبار بنية فعلية
تستخدم SpringBootTest افتراضياً ويب وهمية، بينما تبدأ RANDOM_PORT و DEFINED_PORT مستمعاً. يستخدم NONE سياقاً بلا ويب لكنه قد يهيئ كائن المستخدم واتصاله. اختر النمط والاعتماد، ولا تبدأ الدورة سياقاً أو مستمعاً لإنتاج ادعاء تنفيذ.
لا تتراجع أعمال خادم HTTP في خيط آخر تلقائياً بمعاملة دالة الاختبار. ولا تعيد لهجة بديلة أقفال الإنتاج وترحيله. استخدم تنظيفاً وتخزيناً معزولاً مخولاً، ولا تعتبر كلمة«test» حماية لمصدر المشروع المهيأ؛ فالحد الفعلي هو ما شُغل وأين وصل.
اجعل الفشل والدليل قابلين للتكرار
اضبط الساعة والهوية والبديل والجدولة بدلاً من نوم يجعل التأكيد ينجح غالباً. راقب future الفاشلة والتنظيف، وافحص عدم التعديل الممنوع لا الحالة فقط. احتفظ بعقد DTO للمستهلك وتجنب لقطات أسطر استثناء داخلية أوتشخيص غير ثابت.
سجل النطاق والاعتماد والإصدار والأمر والنتيجة. تفصل الدورة نماذج Java وتحليل JSON/YAML/XML عن اختبار Spring غير المنفذ. تبين المجموعة المفيدة السلوك المتراجع والحد المرصود؛ ولا يساوي اكتشاف الاختبارات أوترجمة DTO اجتياز تكامل الويب والأمان والاستمرارية.
الأخطاء الشائعة وإصلاحها
فتح الاختبار منفذاً غير متوقع.
- لماذا يحدث؟
- اختير نمط ويب فعلي.
- كيف تصلحه؟
- اختر الحد الوهمي أوتكاملاً مخولاً صراحة.
- كيف تتجنب تكراره؟
- راجع نطاق البدء.
بقيت بيانات الخادم بعد تراجع الاختبار.
- لماذا يحدث؟
- عمل الخادم بمعاملة أخرى.
- كيف تصلحه؟
- اعزل ونظف وفق المعمارية.
- كيف تتجنب تكراره؟
- لا تستنتج التراجع من دالة الاختبار وحدها.
نجح اختبار ويب بتعطيل كل المرشحات.
- لماذا يحدث؟
- لم يعد يختبر الأمان المدعى.
- كيف تصلحه؟
- أبق المقصود وأضف هوية أو CSRF مضبوطة.
- كيف تتجنب تكراره؟
- سمّ حد الدليل.
اختبر فهمك
1. أي اختبار يرى ربط JSON و 400 دون منفذ؟
اعرض الحل المشروح
شريحة MVC أوويب وهمية تضم المتحكم والنصيحة والتحقق والمرشحات. يتجاوز النداء المباشر ذلك ويضيف المنفذ العشوائي حدوداً أخرى.
2. لماذا لا يثبت MockitoBean SQL المولد؟
اعرض الحل المشروح
يستبدل السلوك ولا ينفذ JPA. يثبت الاستدعاء وتحويل النتيجة المعطاة، وتحتاج الخرائط والقيود والخطة والمعاملة اختبار قاعدة منفصلاً.
أهم ما تعلمته
- طابق نطاق الاختبار بالادعاء.
- تختلف ويب وهمية وسياق ضبط ومستمع فعلي.
- يشمل الدليل الصادق الفشل والتنظيف والحدود.