myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Kito Mann <kito.m...@virtua.com>
Subject Re: [core][mftest][discuss] Create new module for JUnit Mock Testing using MyFaces Core, MyFaces Test and CDI (OWB)
Date Sun, 26 Jan 2014 02:50:27 GMT
Hello Leonardo,

This sounds very cool. Why not add it to MyFaces-Test instead?

On Saturday, January 25, 2014, Leonardo Uribe <lu4242@gmail.com> wrote:

> Hi
>
> With JSF 2.0/2.1 and with the introduction of JSF 2.2, it has become more
> and
> more frequent to find cases where you have a JSF-CDI application, and you
> want
> to create JUnit tests. Usually, the interest in these cases is test some
> complex server side logic, but the problem is you usually need some
> control of
> the JSF lifecycle, or there is an interaction between pages and beans and
> with a mocked environment like the one provided in MyFaces Test you can
> only
> simulate partially the beans. In these cases, it is not necessary to fully
> simulate the client, because what you really want to check is what's going
> on
> in the server side.
>
> Solutions like the one provided by JSFUnit or Arquillian does not fit
> properly
> in these cases, because the server does not run on the same side as the
> client,
> so there are 2 running classloaders (the one where junit is and the other
> that belongs to the web server) which makes debugging difficult.
>
> Additionally, some time ago, these issues were opened in MYFACESTEST issue
> tracker:
>
> - MYFACESTEST-42 Implement support for creating managed beans from
>                  faces-config.xml or other JSF config files.
> - MYFACESTEST-59 Move MockViewDeclarationLanguageFactory from MyFaces Core
> to
>                  MyFaces-test
> - MYFACESTEST-62 Move FaceletTestCase from internal MyFaces to the MyFaces
>                  Test project
>
> These issues suggest it would be great to have some mock test environment
> that
> can do things like build a view from a .xhml or read faces-config.xml or
> .taglib.xml files. In few words, run MyFaces Core in a JUnit test.
>
> Looking for a way to fix this problem, some time ago it was created this
> issue:
>
> https://issues.apache.org/jira/browse/MYFACES-3376 Create abstract test
> classes
>                                         that runs MyFaces Core as in a
> container
>
> Inside MyFaces Core Impl module, in src/test/java directory there is a
> package
> called org.apache.myfaces.mc.test.core with these junit base test classes:
>
> - AbstractMyFacesTestCase
> - AbstractMyFacesRequestTestCase
> - AbstractMyFacesFaceletsTestCase
> - AbstractMyFacesCDIRequestTestCase
>
> These classes creates a mock servlet test environment that is able to run
> MyFaces Core using JUnit. For example:
>
> // 1. In pom.xml it is necessary to make available src/main/webapp
> resources
> // as test resources:
>
> <build>
>     <testResources>
>         <testResource>
>             <directory>${project.basedir}/src/test/resources</directory>
>         </testResource>
>         <testResource>
>             <directory>${project.basedir}/src/main/webapp</directory>
>             <targetPath>webapp</targetPath>
>         </testResource>
>     </testResources>
>     <!-- .... -->
>
> // 2. Add beans.xml in src/main/java/META-INF and src/test/java/META-INF
> // 3. Now create the test class
>
> public class SimpleTestCase extends AbstractMyFacesCDIRequestTestCase
> {
>     @Inject
>     @Named("helloWorld")
>     private HelloWorldController helloWorldBean;
>
>     @Test
>     public void testHelloWorld() throws Exception
>     {
>         startViewRequest("/helloWorld.xhtml");
>         processLifecycleExecute();
>         Assert.assertEquals("page2.xhtml", helloWorldBean.send());
>         renderResponse();
>
>         client.inputText("mainForm:name", "John Smith");
>         // The button end current request and start a new request
>         // with a simulated submit
>         client.submit("mainForm:submit");
>
>         processLifecycleExecute();
>         Assert.assertEquals("John Smith", helloWorldBean.getName());
>         Assert.assertEquals("/page2.xhtml",
>                          facesContext.getViewRoot().getViewId());
>         endRequest();
>     }
>
>     @Override
>     protected ExpressionFactory createExpressionFactory()
>     {
>         // By default it uses a mock ELFactory.
>         return new com.sun.el.ExpressionFactoryImpl();
>     }
>
>     @Override
>     protected String getWebappContextFilePath()
>     {
>         // By default it is the package name of the test.
>         return "webapp";
>     }
>
> }
>
> The example simulates a helloworld submit. getWebappContextFilePath()
> defines
> the link between the webapp context as test resource, to allow the test to
> load the resources from that location. All faces-config.xml and .taglib.xml
> from the classpath are automatically loaded. JSF annotation scanning is
> disabled by default but you can enable it overriding isScanAnnotations()
> method and setting up "org.apache.myfaces.annotation.SCAN_PACKAGES" param
> to reduce the time spent in classpath scanning.
>
> This code has allowed us to make very complex tests inside MyFaces Core
> very
> easily, like Faces Flows, Resource Library Contracts, Reset Values or View
> Pooling. The resulting simulated environment is almost identical in
> comparison
> with the one created inside a web server, and the differences can be fixed
> quite easily, overriding the appropiate methods. The integration with
> CDI is just register the servlet listener and that's it.
>
> If users are using some JSF third-party component library, it is quite easy
> to create a custom mock client and use Firebug or something else to check
> the http requests and provide some methods to fill the simulated client
> side logic.
>
> Create test cases is pretty straightforward, because everything is running
> in the junit test case, so you don't need to write any callback, just write
> the instructions and do the necessary validations in the right spots. This
> is
> how a redirect is simulated:
>
>     @Test
>     public void testRedirect1() throws Exception
>     {
>         startViewRequest("/redirect1.xhtml");
>         processLifecycleExecute();
>         renderResponse();
>         client.submit("mainForm:submit");
>         processLifecycleExecuteAndRender();
>         // redirect sends 302 response, so the client must take it and
>         // start the redirected request
>         client.processRedirect();
>         // this is the lifecycle of the redirected request.
>         processLifecycleExecuteAndRender();
>         String redirectedContent = getRenderedContent();
>         Assert.assertTrue(redirectedContent.contains("Redirected Page"));
>     }
>
> The code tries to reuse as much configuration info as possible. For example
> a test case like FlowMyFacesRequestTestCase in my machine in Netbeans
> takes 2.5 seconds to be executed and then 0.17 seconds per each additional
> test, and the IDE takes another 3 or 4 seconds to execute
> "compile on save" and start junit. CDI takes about 1.1 seconds per method.
> Note this is a lot less than deploy a server like jetty or tomee, which in
> the same conditions could take (with a helloworld app) about 10 seconds or
> more to start, run the test and stop.
>
> The proposal I have for the consideration of MyFaces community is create a
> new module for MyFaces Core 2.2 branch called impl-test. The module takes
> the code from org.apache.myfaces.mc.test.core in impl module and repackage
> it into a new jar file so users can reference it into its own projects.
> In that way we can use the code in MyFaces Core like we are doing right
> now and we can maintain it at the same time.
>
> This is the issue in jira to keep track of this feature:
>
> https://issues.apache.org/jira/browse/MYFACES-3849
>
> I have already committed the necessary code so you can just take it from
> trunk and try it. If no objections, I'll include the module into the next
> release of MyFaces Core. This is also a good moment to provide ideas about
> how to improve this feature, so suggestions are welcomed.
>
> regards,
>
> Leonardo Uribe
>


-- 
___

Kito D. Mann | @kito99 | Author, JSF in Action
Virtua, Inc. | http://www.virtua.com | JSF/Java EE training and consulting
http://www.JSFCentral.com | @jsfcentral
+1 203-998-0403

* Listen to the Enterprise Java Newscast: *http://w
<http://blogs.jsfcentral.com/JSFNewscast/>ww.enterprisejavanews.com
<http://ww.enterprisejavanews.com>*
* JSFCentral Interviews Podcast:
http://www.jsfcentral.com/resources/jsfcentralpodcasts/
* Sign up for the JSFCentral Newsletter: http://oi.vresp.com/?fid=ac048d0e17

Mime
View raw message