فشل تحديث محتوى ModalWindow في اختبار الوحدة بينما تعمل الوظيفة الفعلية كما هو متوقع - ما الخطأ الذي أفعله؟
سؤال
لذا، قضيت بضع ساعات في البداية محاولًا "إصلاح" هذا الأمر بنفسي ثم البحث في Google كالمجنون ولكنني لم أجد أي شيء من شأنه أن يساعد، لذا أنا هنا الآن.
في الأساس لدي العرف Panel
داخل ويكيت ModalWindow
وبما أنني أحب اختبار الوحدة، أريد اختباره.السلوك المحدد هنا هو تحديث ملف ModalWindow
محتوى :في الكود الفعلي الذي قمت باستخراجه منه، تعمل معالجة أحداث Ajax على إعادة تحميل أشياء جديدة إلى لوحة المحتوى، وقد قمت فقط بإزالة تلك العناصر لجعلها أقصر.
إذن، هنا Panel
رمز
package wicket.components;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.*;
public class MyModalWindowPanel extends Panel {
private Form form;
private ModalWindow modal;
public MyModalWindowPanel(String id, ModalWindow modal) {
super(id);
this.setOutputMarkupId(true);
this.modal = modal;
initializeForm();
addBasicDataFieldsToForm();
add(campaignForm);
}
private void initializeForm() {
form = new Form("form");
form.setOutputMarkupId(true);
}
private void addBasicDataFieldsToForm() {
campaignForm.add(new AjaxButton("infoSubmit",
new Model<String>("Ajaxy Click")) {
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
modal.setContent(new MyModalWindowPanel(modal.getContentId(),
modal));
modal.show(target);
}
});
}
}
والترميز المقابل
<wicket:panel>
<form wicket:id="form">
<input type="submit" value="Ajaxy Click" wicket:id="infoSubmit" />
</form>
</wicket:panel>
لاحظ أنه عند التشغيل في حاوية servlet مثل Tomcat، فإن هذا يعمل بشكل صحيح - لا توجد أخطاء وظيفية هنا!
إذن ما هي المشكلة إذن؟لا يبدو أنني قادر على الحصول على اختبار الوحدة لهذا العمل!يبدو صف الاختبار الخاص بي للوحة هكذا
package wicket.components;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.util.tester.*;
import junit.framework.TestCase;
public class MyModalWindowPanelTestCase extends TestCase {
private WicketTester tester;
private ModalWindow modal;
@Override
protected void setUp() throws Exception {
tester = new WicketTester();
modal = new ModalWindow("modal");
tester.startPanel(new TestPanelSource() {
public Panel getTestPanel(String id) {
return new MyModalWindowPanel(id, modal);
}
});
}
public void testReloadingPanelWorks() throws Exception {
// the next line fails!
tester.executeAjaxEvent("panel:campaignForm:campaignInfoSubmit",
"onclick");
tester.assertNoErrorMessage();
}
}
وإليك أثر المكدس الناتج لتشغيل ذلك
java.lang.IllegalStateException: No Page found for component [MarkupContainer [Component id = modal]]
at org.apache.wicket.Component.getPage(Component.java:1763)
at org.apache.wicket.RequestCycle.urlFor(RequestCycle.java:872)
at org.apache.wicket.Component.urlFor(Component.java:3295)
at org.apache.wicket.behavior.AbstractAjaxBehavior.getCallbackUrl(AbstractAjaxBehavior.java:124)
at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.getCallbackScript(AbstractDefaultAjaxBehavior.java:118)
at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.getCallbackScript(AbstractDefaultAjaxBehavior.java:106)
at org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow$WindowClosedBehavior.getCallbackScript(ModalWindow.java:927)
at org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow.getWindowOpenJavascript(ModalWindow.java:1087)
at org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow.show(ModalWindow.java:352)
at wicket.components.MyModalWindowPanel$1.onSubmit(MyModalWindowPanel.java:45)
at org.apache.wicket.ajax.markup.html.form.AjaxButton$1.onSubmit(AjaxButton.java:102)
at org.apache.wicket.ajax.form.AjaxFormSubmitBehavior.onEvent(AjaxFormSubmitBehavior.java:143)
at org.apache.wicket.ajax.AjaxEventBehavior.respond(AjaxEventBehavior.java:177)
at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.onRequest(AbstractDefaultAjaxBehavior.java:299)
at org.apache.wicket.util.tester.BaseWicketTester.executeAjaxEvent(BaseWicketTester.java:1236)
at org.apache.wicket.util.tester.BaseWicketTester.executeAjaxEvent(BaseWicketTester.java:1109)
at wicket.components.MyModalWindowPanelTestCase.testReloadingPanelWorks(MyModalWindowPanelPanelTestCase.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:81)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
لذا، كيف يمكنني/يجب أن أقوم بإصلاح اختبار الوحدة الخاص بي حتى ينجح؟
المحلول
سأخرج على أحد الأطراف هنا وأقول:أضف مكون اللوحة الخاص بك إلى صفحة للاختبار.
AFAIK لا يمكنك اختبار المكونات الفردية، ولكن يجب إعداد اختبار عن طريق الحصول على صفحة والقيام بتأكيدات على ذلك..
هذا ما أستخدمه للاختبار:
public class TestHomePage {
private static WicketTester tester;
@BeforeClass
public static void setUp() {
tester = new WicketTester(new WicketApplication() {
@Override
protected void init() {
//Override init to use SpringUtil's SpringContext due to missing WebApplicationContext
addComponentInstantiationListener(new SpringComponentInjector(this, SpringUtil.getContext()));
}
});
}
@Test
public void testRenderMyPage() {
//start and render the test page
tester.startPage(HomePage.class);
//assert rendered page class
tester.assertRenderedPage(HomePage.class);
//assert page contents
tester.assertContains("Welcome to my webpage");
}
}
يرجى تصحيح لي إذا كنت مخطئا!
نصائح أخرى
رمز "الإنتاج" الذي يظهر أنه يعمل ظاهريًا غير متناسق.أظن أن المتغير CampaignForm من المفترض أن يكون نموذج الحقل.
لكنني أعتقد أن المشكلة الجذرية تكمن في أن النافذة المشروطة نفسها ليست متصلة فعليًا بأي مكون، وبالتالي لا يمكن عرضها.
إذا كان في الكود الحقيقي، فقد تم إرفاقه في مكان ما خارج مكون MyModalWindowPanel الخاص بك، فستحتاج بالتأكيد إلى إرفاقه في مكان ما في الاختبار أيضًا، على الأرجح عن طريق جعل الاختبار الخاص بك يبني إما صفحة اختبار أو لوحة اختبار تحتوي على كل من النافذة المشروطة و المكون تحت الاختبار.
المرة الوحيدة التي حصلت فيها على استثناء "لم يتم العثور على صفحة" كانت عند محاولة الاتصال بـ getPage() في مُنشئ اللوحة.يتم تنفيذ المُنشئ قبل إضافة اللوحة إلى الصفحة، لذلك لا يتم العثور على أي شيء...هل ربما تفعل شيئا من هذا القبيل؟ربما يعمل هذا الرمز في الإنتاج، لكنه لا يزال يرمي هذا الخطأ وراء الكواليس؟
أعلم أن هذا ليس ما تبحث عنه، لكنني وجدته السيلينيوم لتكون أداة عظيمة لاختبار واجهة المستخدم على شبكة الإنترنت.يعد JUnit رائعًا لاختبار المنطق، لكن السيلينيوم مناسب بشكل أفضل للتأكد من ظهور الشيء الصحيح في واجهة المستخدم الخاصة بك.يبدو الأمر غريبًا مع واجهة المستخدم الرسومية الخاصة به وما إلى ذلك، ولكنه يعمل بشكل رائع، وإذا بحثت قليلاً، يمكن الوصول بسهولة إلى واجهة برمجة التطبيقات النصية.