From: Vincent M. <vm...@oc...> - 2001-08-08 14:36:12
|
After thinking a bit more, I now understand what I meant and why I said you had to understand internally how Struts work. This is true in some cases and stems from the fact that Struts is using Base classes instead of interfaces and thus these base classes have some logic in them ... You'll understand what I mean below ... Let's take the following example : public final class LogonAction extends Action { public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // Extract attributes we will need Locale locale = getLocale(request); [...] } The getLocale() method is actually implemented in the Action class ... So I can see 2 ways of coping with this : * Solution 1: Create a LogonActionForTest class that extends LogonAction and override the getLocale() method so that it returns what we want, * Solution 2: Read the source, to find that actually Struts looks into the session for a variable that contains the Locale. Then, write something like public void testXXX() { mockSession.put(Action.LOCALE_KEY, <our locale>); myAction.perform(....); ... } If we use the Cactus approach, i.e. initialize ActionServlet as in real (using the struts-config.xml file), this key will be placed by Struts automatically in the session and we won't have to implement either solution 1 or solution 2. Note that we are *not* interested in finding out what happens if they locale is not correctly set as Struts is supposed to handle that and always return a valid Locale. However we are interested in finding out that our code behaves well with different locales. Regarding Mock Object, it seems to me that Solution 1 is more in the spriti of MO. Potential problems with Solution 1 : * It will only work if our Action class is not declared final ... * It will fail if there is some (badly written) code that verifies the class of the Action and expects a LogonAction class (it will get a LogonActionForTest class instead) and not a derived one. Thoughts? Thanks -Vincent ----- Original Message ----- From: "Vincent Massol" <vm...@oc...> To: <cac...@ja...> Sent: Wednesday, August 08, 2001 3:16 PM Subject: Re: Another point of Mock vs In-Container approach > Let me answer some of my points ... > > ----- Original Message ----- > From: "Vincent Massol" <vm...@oc...> > To: <cac...@ja...> > Cc: <moc...@li...> > Sent: Wednesday, August 08, 2001 1:55 PM > Subject: Another point of Mock vs In-Container approach > > > > I was thinking about unit testing Struts Actions. > > > > Introduction > > ------------ > > > > Writing a Struts Action is very simple: you simply have to provide a > perform > > method with the following signature : > > > > public ActionForward perform(ActionMapping mapping, > > ActionForm form, > > ServletRequest request, > > ServletResponse response) > > > > > > Thus, in order to use Mock Objects for unit testing your action you have > to > > provide mock implementations of : > > - ActionMapping, > > - ActionForm, > > - ServletRequest, > > - ServletResponse, > > - ActionServlet : an instance of this class is provided to your action and > > you can use it to perforl several things. It can be set by calling the > > setServlet(ActionServlet) method on your Action class. > > > > Problem > > --------- > > > > The issue is that Struts initialize internally a lot of objects and put > them > > in different scopes : session, servlet context, request, ..., which is > fine. > > What it simply means is that if you want to unit test your Action class, > > you'll need to understand in details how Struts works internally and stuff > > the session, context, ... with the expected values. To do that you'll have > > to read the source code and spend quite a lot of time (even though Sturts > is > > really well designed by composition). I think this is a major hurdle for > > using Mock Objects when your object to test is using APIs that are not > yours > > ... Struts is open source so it is feasible to look a the source. For non > > open-source framework, it is even harder ... > > well, I don't know what happened to me ... I must have knocked my head > somewhere ... because this is not true at all .... Using Mock Object we just > need to understand what the public methods return (not how it works > internally!) ... > > > The second objection is that > > doing all this initialization takes a lot of lines of code and is a tiring > > process. > > > > maybe true ... will need an example though to prove it... > > > Now, would it be easier with Cactus ? I think so ... for the following > > reasons. > > Here is how you would do it with Cactus : > > > > ActionServlet servlet = new ActionServlet(); > > servlet.init(config); > > > > this is true! MO cannot beat this ... > > > (you'll also have to provide a struts-config.xml file but that's fine as > you > > have to write one for Struts anyway). > > that's all, Struts is initialized ! You don't need to understand how > struts > > works internally. Of course, you could do the same with Mock Objects but > > you'll no longer be following the Mock Objects principles. > > > > Conclusion > > ----------- > > > > Mock Objects has limitations in the following areas : > > - when the API to mock is not yours and especially if you don't have > access > > to the source code because :; > > - it takes time to understand how the API works internally > > no! > > > - it takes time for every test to initialize the API environment > properly. > > maybe > > > - it is difficult when your class to test is using an Application (as > > opposed to a framework). A framework is for exemple a logging framework, > it > > contains no state and no business logic, so it is easy to mock. However a > > framework like Struts is actually an Application : it has state and it has > > logic, thus you need to understand its internal functioning to mock it. > > not completely sure it is wrong, maybe there is some truth in that... > > > > > I would very much like to have you thoughts on that, especially if you > don't > > agree ! :) > > please don't flame me ... :) > > > Thanks > > > > -Vincent > > > > > > |