Feature Requests item #1287539, was opened at 2005-09-11 15:06
Message generated for change (Tracker Item Submitted) made by Item Submitter
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=684978&aid=1287539&group_id=119783

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: core
Group: 1.2
Status: Open
Priority: 5
Submitted By: Ingram Chen (ingramchen)
Assigned to: Nobody/Anonymous (nobody)
Summary: Enhanced MockWebApplication For Testing Controller Logic

Initial Comment:
I have written a WicketTester, which extends 
MockWebApplication, to help testing WebPage without the 
container. WicketTester is mainly used for tesing
controller 
logic and form validation.

the usage of WicketTester will look like:
======================================

(1) case 1: testing WebPage with default constructor

// production code:
public class ManageBook extends WebPage {
   public ManageBook() {
       add(new Link("toCreate") {
          protected void onClick() {
            setResponsePage(CreateBook.class);
          }
       }) ;
   }
}

// test code:
public void testLinkCreateBook() {
    WicketTester tester = new WicketTester();

    //open the test page
    tester.start(ManageBook.class);

    //do controller logic, such as click/forward
    tester.clickLink("toCreate");
 
    // assert correctly forward/redirect.
    tester.assertRenderedPage(CreateBook.class);
}

(2) case 2: testing WebPage that has custom constructor

// production code:
public class ViewBook extends WebPage {
     public ViewBook(Book book) {
          add(new Label("id", book.getId()) ;
          add(new Label("name", book.getName()) ;
     }
}

// test code:
public void testViewBook() {
    WicketTester tester = new WicketTester();

    //for WebPage without default consturctor, I
    //define a TestPageSource to let the page 
    //be instatiated lately.
    tester.start(new TestPageSource() {
        public WebPage getTestPage() {
            Book mockBook = new Book("xxId","xxName");
            return new ViewBook(mockBook);
        }
    });

    // assertion
    tester.assertRenderedPage(ViewBook.class);
    tester.assertLabel("id", "xxId" );
    tester.assertLabel("name", "xxName" );
}

(3) case 3: testing with Form validaiton and submission:

// production code:
public class CreateBook extends WebPage {
    public CreateBook() {
       add(new CreateForm("createForm") );
    }

    // a form with simple validation
    public static class CreateForm extends Form {
       public CreateForm(String id....) {
          super(id, .....) ;
          add(new RequiredTextField("id" ) ;
          add(new RequiredTextField("name" ) ;
       }

       //submit and leave a message on next page.
       protected void onSubmit() {
           //write into db....
           SuccessPage page = new SuccessPage();
           page.info("book created") ;
           setResponePage(page) ;

           //expire old page to prevent user re-submit:
           getSession().remove(getPage());
       }
    }
}

//Test code:
public void testCreateBook_validateFail() {
   WicketTester tester = new WicketTester();
   tester.start(CreateBook.class);

   //submit directly without any input:
   tester.submitForm("createForm");

   tester.assertRenderedPage(CreateBook.class);

   //assert error message from validation
   tester.assertErrorMessages("id is required"
         , "name is required");
}


public void testCreateBook_validatePass() {
   WicketTester tester = new WicketTester();
   tester.start(CreateBook.class);

   //create a FormTester for specific Form
   //in current rendered page.
   FormTester createFormTester = tester
         .prepareFormTester("createForm");

   //simulate user input in FormComponent:
   createFormTester.setValue("id", "xxId");
   createFormTester.setValue("name", "xxName"); 

   //submit the form:
   createFormTester.submit();

   tester.assertRenderedPage(SuccessPage.class);

   //assert info message present.
   tester.assertInfoMessages("book created");

   //assert previous page expired.
   tester.assertExpirePreviousPage();
}

=====================================

The attachements are the implementation I use. 
To archive above features, However, I do some hacks 
because limitation on MockWebApplicaion...

(1) processRequestCycle() always process request twice, 
    I can't figure out why this is necessary (because 
    of redirect ?) and this makes testing controller logic 
    difficult. I write another processRequestCycleOnce()
    instead.
    
(2) When production code raises exception, requestCycle
will 
    redirect to ExceptionErrorPage with exception
stacktrace.
    Sometimes this makes testcase pass silently. It
would be
    helpful that one can obtain RootCause Exception in 
    ExceptionErrorPage: 
    
    public class ExceptionErrorPage extends WebPage  {
      private transient Throwable rootCause ;
      public Throwable getRootCause() {
         return rootCause ;
      }
    }

    With this, we can stop the testCase and prompt 
    with useful assetion message.

    (currently I parse the "exception" message in 
     ExceptionErrorPage manually...)
    
(3) One may configure a global resource file for whole 
    application:

    MyWebApplication.java
    MyWebApplication.properties

    but the MockWebApplication.java doesn't seek 
    MyWebApplication.properties, and this makes 
    the component that refering global resource fail 
    in testing.
    
    It would be helpful that one can configure 
    MockWebApplication.java to refer 
    MyWebApplication.properties.

    (currently I do manually copy...)
    
(4) add a method in Session to veriy whether the page is 
    in the PageMap:

    boolean Session.contain(Page page)
    
    with this, one can verify
getSession().remove(getPage()) 
    work or not.
    
    (currently I use reflection to direct access
     MostRecentlyUsedMap... very bad idea...)


In short, providing above features is sufficient. For 
the long term, I hope there will be an offical
WicketTester 
or WicketTestCase that with more correct implementation.


----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=684978&aid=1287539&group_id=119783


-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
_______________________________________________
Wicket-develop mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/wicket-develop

Reply via email to