Test unitario L'aggiornamento del contenuto di ModalWindow non riesce mentre la funzionalità effettiva funziona come previsto: cosa sto facendo di sbagliato?
Domanda
Quindi, ho trascorso un paio d'ore prima a provare a "riparare" questo me stesso e poi googling come un pazzo ma non ho trovato nulla che potesse aiutare così ora sono qui.
Fondamentalmente ho un pannello
personalizzato all'interno del ModalWindow
di Wicket e poiché mi piace il test unitario, voglio testarlo. Il comportamento specifico qui è l'aggiornamento del contenuto di ModalWindow
: Nel mio codice effettivo da cui l'ho estratto, la gestione degli eventi Ajax ricarica effettivamente nuovi elementi nel pannello dei contenuti, li ho appena rimossi per renderli più brevi.
Quindi, ecco il pannello
codice di
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);
}
});
}
}
e il markup corrispondente
<wicket:panel>
<form wicket:id="form">
<input type="submit" value="Ajaxy Click" wicket:id="infoSubmit" />
</form>
</wicket:panel>
Si noti che quando eseguito in un servlet container come Tomcat, questo funziona correttamente - qui non ci sono bug funzionali!
Quindi qual è il problema allora? Apparentemente non riesco a ottenere il test unit perché funzioni! La mia classe di test per il panel è simile a questa
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();
}
}
ed ecco la risultante stacktrace di eseguirla
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)
Quindi, come posso / dovrei riparare il mio test unitario in modo che possa passare?
Soluzione
Esco di un arto qui e dico: aggiungi il componente del tuo pannello a una pagina per il test ..
AFAIK non puoi testare i singoli componenti, ma dovresti impostare un test ottenendo una pagina e facendo affermazioni su questo.
Questo è quello che uso per i test:
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");
}
}
Per favore, correggimi se sbaglio!
Altri suggerimenti
La "produzione" codice mostrato che apparentemente funziona è incoerente. Ho il sospetto che la variabile campaignForm dovrebbe essere la forma del campo.
Ma penso che il problema principale sia che la finestra modale stessa non è in alcun modo collegata a un componente e quindi non può essere visualizzata.
Se nel codice reale, è collegato da qualche parte al di fuori del componente MyModalWindowPanel, dovrai sicuramente collegarlo anche da qualche parte nel test, probabilmente facendo in modo che il tuo test crei una pagina di test o un pannello di test che contenga entrambi i finestra modale e componente sotto test.
L'unica volta che ho ottenuto "Nessuna pagina trovata" l'eccezione era quando si cercava di chiamare getPage () in un costruttore di pannelli. Il costruttore viene eseguito prima che il pannello venga aggiunto a una pagina, quindi non viene trovato nulla ... Stai forse facendo qualcosa del genere? Forse questo codice funziona in produzione, ma sta ancora gettando questo errore dietro le quinte?
So che non è quello che stai cercando, ma ho trovato Selenium essere un ottimo strumento per test dell'interfaccia utente web. JUnit è eccezionale per testare la logica, ma Selenium è più adatto per assicurarsi che la cosa giusta venga visualizzata nell'interfaccia utente. Sembra complicato con la sua interfaccia gui e simili, ma funziona benissimo e se si scava un po 'l'API di scripting è facilmente accessibile.