JSFUnit tests use the HttpSession as a conduit for the FacesContext. Here is what happens behind the scenes during a JSFUnit test:
JUnit calls Cactus to run your test from the container.
The JSFUnitFilter puts a reference to the HttpSession in a ThreadLocal variable
Your test code calls new JSFSession("/mypage.faces"). At this point a new HtmlUnit WebClient is created with the same session id as the Cactus session. This allows the JSF request to execute in the same session as Cactus.
When the JSF request is done, the FacesContext is placed in the HttpSession. Now your test thread has access to the FacesContext left over from the last request.
JSFUnit Thread Considerations
The current design of JSFUnit shown above has some thread considerations. First, understand that there are two threads in a JSFUnit test. These are the Test Thread and the JSF Request Thread
The Test Thread
This is the thread from the Cactus request that passes through the JSFUnitFilter and executes your test code. When your test executes a JSF request, the Test Thread will block until the JSF request is complete. Then it will continue executing your test code.
The JSF Request Thread
The JSF Request Thread runs whenever you make a request to the server from your test code. This is a normal servlet request thread that happens to share the same HttpSession instance as your test.
Multi-Client, Mult-threaded Tests
Each time you create a JSFSession, the HttpSession is cleared but not destroyed. Therefore, a multi-threaded test where two JSFSession instances are making JSF requests at the same time is not supported. The reason is that all JSFSession instances are using the same HttpSession and they would be in conflict. This may be addressed in a future release.