|
From: Matt R. <li...@ra...> - 2004-04-27 19:55:39
|
+1 for including the polished Servlet API mocks in the main Spring
codebase. Here's an example of a UserFormControllerTest to test a
SimpleFormController using these mocks. They're not used much in this
example, but they sure make things a lot easier. The alternative is to
use Cactus to test these, but I've grown to loathe waiting for my
container to startup and run this stuff.
Matt
public class UserFormControllerTest extends TestCase {
private static Log log =3D
LogFactory.getLog(UserFormControllerTest.class);
private ApplicationContext ctx;
private UserFormController c;
public void setUp() throws Exception {
String[] paths =3D { "/applicationContext.xml",
"/action-servlet.xml" };
ctx =3D new ClassPathXmlApplicationContext(paths); =20
c =3D (UserFormController) ctx.getBean("userFormController");
}
=20
public void testDisplayEmptyForm() throws Exception {
MockHttpServletRequest request =3D
new MockHttpServletRequest(null, "GET", "/editUser.do");
HttpServletResponse response =3D new MockHttpServletResponse();
ModelAndView mv =3D c.handleRequest(request, response);
assertTrue("returned correct view name",
mv.getViewName().equals("userForm"));
}
public void testAddUser() throws Exception {
MockHttpServletRequest request =3D
new MockHttpServletRequest(null, "POST", "/editUser.do");
request.addParameter("firstName", "Matt");
request.addParameter("lastName", "Raible");
HttpServletResponse response =3D new MockHttpServletResponse();
ModelAndView mv =3D c.handleRequest(request, response);
Errors errors =3D
(Errors) mv.getModel().get(BindException.ERROR_KEY_PREFIX +
"user");
assertTrue("no errors returned in model", errors =3D=3D null);
assertNotNull(request.getSession().getAttribute("message"));
}
public void testSaveUserMissingLastName() throws Exception {
MockHttpServletRequest request =3D
new MockHttpServletRequest(null, "POST", "/editUser.do");
request.addParameter("firstName", "Julie");
HttpServletResponse response =3D new MockHttpServletResponse();
ModelAndView mv =3D c.handleRequest(request, response);
Errors errors =3D
(Errors) mv.getModel().get(BindException.ERROR_KEY_PREFIX +
"user");
assertTrue("errors returned in model", errors !=3D null);
assertNull(request.getSession().getAttribute("message"));
} =20
}
> -----Original Message-----
> From: spr...@li...
> [mailto:spr...@li...]
> On Behalf Of j=FCrgen h=F6ller [werk3AT]
> Sent: Tuesday, April 27, 2004 11:58 AM
> To: spr...@li...
> Cc: spr...@li...
> Subject: [Springframework-developer] Re:=20
> [Springframework-user] Testing Controllers and FormControllers
>=20
>=20
> Matt, everybody,
>=20
> Essentially, the Servlet API mocks in Spring's test directory
> are just there because the MockObjects=20
> (http://www.mockobjects.com) Servlet API mocks are so=20
> inconvenient to use. The current Spring-provided Servlet API=20
> mocks are by no means in a polished state, though: They're=20
> just good enough for being used within the framework test=20
> suite. They'd need some serious refinement for making them=20
> public - after all, we have a reputation to lose :-)
>=20
> So on that occasion, I've reworked those mocks today, making
> them significantly more complete than before, and ready for=20
> getting included in the Spring distribution. The question is:=20
> Where to include them? I'd like to include them in the main=20
> Spring sources, in a org.springframework.web.mock package:=20
> They would naturally be part of spring.jar and spring-web.jar=20
> then. The test directory (where they currently reside) is no=20
> appropriate place, as it is about testing the framework=20
> rather than providing infrastructure classes.=20
>=20
> While it isn't in general appropriate to include mocks in the
> main Spring codebase, I guess this is a different case: Those=20
> mocks are specifically provided to ease testing of Spring web=20
> contexts (like XmlWebApplicationContext or=20
> StaticWebApplicationContext that need a ServletContext) and=20
> controllers (the Controller.handleRequest method needs an=20
> HttpServletRequest and an HttpServletResponse). Including=20
> them in the standard distribution would also indicate our=20
> strong focus on testability.
>=20
> The new MockServletContext implementation uses the
> org.springframework.core.io.Resource API for resource=20
> loading, to allow for ServletContext.getResourceAsStream from=20
> any resource base. So partly, the mock implementations depend=20
> on low-level Spring API. We could of course keep the mocks in=20
> a separate part of the Spring CVS, but it's just about a=20
> couple of classes, thus hardly worth a separate source tree.
>=20
> IMO, the main concern regarding additions to the main Spring
> codebase is whether those additions can potentially grow=20
> significantly: While Keith's rules API in the sandbox has=20
> definite potential there (so had Ben Alex' security framework=20
> that became the Acegi Security System), the recent Struts=20
> support classes and those Servlet API mocks will at best see=20
> slight refinements but certainly not exponential growth. So=20
> the former seems like a candidate for a separate module to=20
> me, while the latter should fit into the main Spring codebase.
>=20
> An important point to consider is that there are simply no
> mocks necessary for testing most parts of a typical Spring=20
> app, respectively just interfaces that can conveniently be=20
> mocked in a dynamic fashion with EasyMock. There are just two=20
> exceptions, as far I see: Our SimpleNamingContext stuff eases=20
> custom JNDI environments, and the newly refined set of=20
> Servlet API mocks allows for convenient testing of Spring web=20
> MVC (and web contexts).
>=20
> Mocking an EJB container is next to impossible, so that's not
> worth further consideration. JDBC can quite nicely be mocked=20
> with EasyMock; it's preferable to use the JdbcOperations=20
> interface as far as possible, though. Same for a Hibernate=20
> Session, with HibernateOperations being preferable. It's more=20
> or less just the Servlet API that's really tedious to mock=20
> with EasyMock, due to all those interdependent methods (e.g.=20
> URL paths, parameters, attributes).
>=20
> What does everybody think? Does anyone mind including those
> polished Servlet API mocks in the main Spring codebase,=20
> already for 1.0.2? Any suggestions for alternatives?
>=20
> Juergen
>=20
>=20
> -----Original Message-----
> From: spr...@li...=20
> [mailto:spr...@li...]On Behalf Of=20
> Matt Raible=20
> Sent: Saturday, April 24, 2004 2:02 PM=20
> To: spr...@li...=20
> Subject: Re: [Springframework-user] Testing Controllers and=20
> FormControllers=20
>=20
>=20
> I use StrutsTestCase (http://strutstestcase.sf.net), which
> allows you =20
> to write very little code to test an Action. Here is a=20
> simple example =20
> of testing an "execute" method:=20
>=20
> package org.appfuse.webapp.action;
>=20
> import servletunit.struts.CactusStrutsTestCase;
> import org.appfuse.Constants;=20
>=20
> public class PersonActionTest extends CactusStrutsTestCase {
> =20
> public PersonActionTest(String name) {=20
> super(name);=20
> }
>=20
> public void testExecute() {=20
> // test execute method=20
> setRequestPathInfo("/editPerson");=20
> addRequestParameter("id", "1");=20
> actionPerform();=20
> verifyNoActionErrors();
> =20
> assertNotNull(getRequest().getAttribute(Constants.PERSON_KEY));=20
> }
>=20
> public static void main(String[] args) {=20
> junit.textui.TestRunner.run(PersonActionTest.class);=20
> }
> }=20
>=20
> Since CactusStrutsTestCase extends from Cactus, I can also
> use Cactus's =20
> FormAuthentication support to mimic container-managed authentication.=20
>=20
> To test a "Save" is also pretty simple.
>=20
> public void testSave() throws Exception {=20
> setRequestPathInfo("/editPerson");=20
> addRequestParameter("action", "Edit");=20
> addRequestParameter("id", "1");
>=20
> actionPerform();
>=20
> =20
> assertTrue(getRequest().getAttribute(Constants.PERSON_KEY) !=3D
> null);=20
>=20
> setRequestPathInfo("/savePerson");=20
> addRequestParameter("action", "Save");=20
> actionPerform();=20
> verifyForward("edit");=20
> verifyNoActionErrors();=20
> }
>=20
> I think you have something similar to this with the Mock
> Object you're =20
> using in Spring. It just needs to be packaged up as a JAR. I'll be =20
> more than happy to write up some documentation on how to use it.=20
>=20
> Matt
>=20
>=20
> On Apr 24, 2004, at 4:27 AM, j=FCrgen h=F6ller [werk3AT] wrote:
>=20
> > Matt,
> >=20
> > I just tried using MockHttpServletRequest and
> MockHttpServletResponse
> > from MockObjects with a Spring FormController.
> Unfortunately, those
> > MockObjects mocks are really not well-suited for testing
> here, as it's
> > so much hassle to setup any kind of HttpServletRequest
> method access.
> > What request/response mocks do you use for testing Struts Actions?
> >=20
> > Juergen
> >=20
> >=20
> > ________________________________
> >=20
> > Von: spr...@li... im Auftrag von
> > j=FCrgen h=F6ller [werk3AT]
> > Gesendet: Sa 24.04.2004 10:57
> > An: spr...@li...=20
> > Betreff: Re: [Springframework-user] Testing Controllers and =20
> > FormControllers=20
> >=20
> >=20
> >=20
> > I don't see much difference between testing Controllers and
> > FormControllers: Both share the same "ModelAndView
> > handleRequest(HttpServletRequest, HttpServletResponse)"=20
> method that
> > you need to invoke for testing. As of 1.0.1, you shouldn't need a
> > ServletContext mock anymore (except when actually accessing the =20
> > ServletContext), so all you need are HttpServletRequest and =20
> > HttpServletResponse mocks. The mocks provided by the MockObjects =20
> > project should be fine for this.=20
> >=20
> > Juergen
> >=20
> >=20
> > ________________________________
> >=20
> > Von: spr...@li... im Auftrag von
> > Matt Raible
> > Gesendet: Fr 23.04.2004 20:48
> > An: spr...@li...=20
> > Betreff: [Springframework-user] Testing Controllers and=20
> FormControllers
> >=20
> >=20
> >=20
> > I've found it pretty simple to test Controllers, but FormControllers
> > are a different story. From looking at the
> FormControllerTestSuite (URL
> > below), as well as many other Spring tests, it seems that a lot of
> > internal mocks are used to test this stuff.=20
> >=20
> > So my question is - what do you recommend for the average Spring MVC
> > person? What is the strategy we should be using to test our=20
> > controllers? Should we be using the Mocks that Spring
> provides? This
> > would certainly make things easier. If we're supposed to
> do that - is
> > it possible to get these mocks distributed in a JAR?
> >=20
> > Thanks,
> >=20
> > Matt
> >=20
> > http://monkeymachine.co.uk/spring/xref-test/org/springframework/web/
> > serv
> > let/mvc/FormControllerTestSuite.html=20
> >=20
> >=20
> >=20
> >=20
> > -------------------------------------------------------
> > This SF.net email is sponsored by: The Robotic Monkeys at ThinkGeek
> > For a limited time only, get FREE Ground shipping on all=20
> orders of $35
> > or more. Hurry up and shop folks, this offer expires April 30th!
> > http://www.thinkgeek.com/freeshipping/?cpg=3D12297=20
> > _______________________________________________=20
> > Springframework-user mailing list=20
> > Spr...@li...=20
> > https://lists.sourceforge.net/lists/listinfo/springframework-user=20
> >=20
> >=20
> >=20
> >=20
> > -------------------------------------------------------
> > This SF.net email is sponsored by: The Robotic Monkeys at ThinkGeek
> > For a limited time only, get FREE Ground shipping on all=20
> orders of $35
> > or more. Hurry up and shop folks, this offer expires April 30th!
> > http://www.thinkgeek.com/freeshipping/?cpg=12297=20
> > _______________________________________________=20
> > Springframework-user mailing list=20
> > Spr...@li...=20
> > https://lists.sourceforge.net/lists/listinfo/springframework-user=20
> >=20
> >=20
> >=20
> >=20
> > -------------------------------------------------------
> > This SF.net email is sponsored by: The Robotic Monkeys at ThinkGeek
> > For a limited time only, get FREE Ground shipping on all=20
> orders of $35
> > or more. Hurry up and shop folks, this offer expires April 30th!
> > http://www.thinkgeek.com/freeshipping/?cpg=12297=20
> > _______________________________________________=20
> > Springframework-user mailing list=20
> > Spr...@li...=20
> > https://lists.sourceforge.net/lists/listinfo/springframework-user=20
>=20
>=20
>=20
> -------------------------------------------------------
> This SF.net email is sponsored by: The Robotic Monkeys at ThinkGeek=20
> For a limited time only, get FREE Ground shipping on all=20
> orders of $35=20
> or more. Hurry up and shop folks, this offer expires April 30th!=20
> http://www.thinkgeek.com/freeshipping/?cpg=12297=20
> _______________________________________________=20
> Springframework-user mailing list=20
> Spr...@li...=20
> https://lists.sourceforge.net/lists/listinfo/springframework-user=20
>=20
>=20
>=20
> -------------------------------------------------------
> This SF.net email is sponsored by: The Robotic Monkeys at ThinkGeek=20
> For a limited time only, get FREE Ground shipping on all orders of $35
> or more. Hurry up and shop folks, this offer expires April 30th!=20
> http://www.thinkgeek.com/freeshipping/?cpg=12297
> _______________________________________________
> Springframework-developer mailing list=20
> Spr...@li...
> https://lists.sourceforge.net/lists/listinfo/springframework-developer
>=20
|