You are viewing a plain text version of this content. The canonical link for it is here.
Posted to adffaces-dev@incubator.apache.org by Matthias Wessendorf <ma...@apache.org> on 2006/06/19 22:31:25 UTC

Re: Thoughts about unit testing and mock objects

Gentlements,

since there is this nice little guy ([1]), I'd like to come back to
this discussion.

Adam and I spoke about starting to solve this problem.
For "JSF infrastructure" things we'd like to give Shale a try.

For stuff like UIComponent / Rendere there might be JMock useful.
Btw. I checked the legal-discuss list and the jMock license (BSD
style) fit's fine into the ASF world.

-Matthias

[1] http://issues.apache.org/jira/browse/ADFFACES-4

On 5/14/06, John Fallows <jo...@gmail.com> wrote:
> On 5/14/06, Adam Winer <aw...@gmail.com> wrote:
> >
> > On 5/14/06, John Fallows <jo...@gmail.com> wrote:
> > > On 5/13/06, Craig McClanahan <cr...@apache.org> wrote:
> > > >
> > > >
> > > > In an example that ought to be relevant for this codebase :-),
> > consider
> > > > what
> > > > happens when you want to test the encodeBegin(), encodeChildren(), and
> > > > encodeEnd() methods of a Renderer implementation.  The methods return
> > > > void,
> > > > so the output isn't particularly interesting :-).  What is
> > interesting,
> > > > however, is that the methods themselves are going to assume that
> > > > FacesContext.getResponseWriter() returns somethng usable, even in a
> > unit
> > > > test scenario.  Shale's MockFacesContext, for example, gives you back
> > a
> > > > mock
> > > > writer that can write out to a buffer, which you can later examine to
> > > > determine whether the component created correct markup or not (based
> > on
> > > > the
> > > > properties/attributes you set on the component).  And, this
> > functionality
> > > > is
> > > > needed in all renderer tests, so it makes sense to encapsulate into a
> > > > separate library that can be debugged once.
> > > >
> > > > How do you approach this sort of scenario with dynamic mocks?
> > >
> > >
> > > Nice example, thanks Craig!
> > >
> > > With dynamic mock objects, you would setup each method call made on the
> > > ResponseWriter which is functionality equivalent, although much more
> > > verbose.
> >
> > Far more so, to the point that I can hardly imagine anyone writing a test
> > like
> > that.  Also, the order of invocations becomes partially important,
> > and partially irrelevant - which attributes are written on which
> > elements are important, which order the attributes are written
> > is irrelevant.  A dynamic mock is never going to have enough
> > semantics to capture this requirement.
>
>
> Surprisingly, jMock does have sufficient semantics, but the ResponseWriter
> buffer approach makes it easier to specify the expected output.
>
> That's why the ADF Faces codebase has a handwritten mock for
> > a response writer that very intentionally *is not* the same response
> > writer we use at runtime:
> >
> >   http://tinyurl.com/m4zth
> >
> > ... and there's no way that the default mock implementation would
> > capture any of the semantics that this test captures.
>
>
> Since you mention this example, the TestResponseWriter seems to include some
> implementation-specific stuff, such as optimized removal of empty span
> elements in the final markup.  For isolated unit testing, we probably ought
> to be unit testing the Renderers to verify that they interact as designed
> with the mock ResponseWriter, and then separately unit testing our
> ResponseWriter implementation to make sure it optimizes correctly.
>
> > Your point is to simplify the effort involved in verifying the result,
> > > right?  That's pretty useful, although this example doesn't appear to
> > > address my question about the behavior that might become incorrect.
> >
> > Simplifying the effort to write a test is crucial, not just pretty useful.
> > Developers are habitually lazy at writing tests, and putting obstacles
> > in their path ensures they won't.
>
>
> Sure.  Like I said above, buffering the Renderer output is a good idea that
> makes it easier to verify the output.
>
> For your question about "behavior that might be incorrect",
> > say I was mocking UIComponent behaviors for a piece of code
> > that will need to invoke findComponent().  How do I mock
> > findComponent()?  Odds are, if I'm writing the test, I mock it
> > to produce exactly the result I want - not necessarily implement the
> > correct algorithm.  Do I know that my test is right?
>
>
> Thanks for the example, this is getting closer to what I'm trying to figure
> out. :-)
>
> Suppose there are two codepaths in such a unit test, one that expects a
> non-null component from findComponent, and another codepath that handles the
> null case.
>
> As a unit test writer, I don't need to be concerned about how findComponent
> is actually implemented, just that there are only two possible results
> affecting the codepath, null and non-null.  If the unit tests are isolated,
> then there would be a separate unit test for UIComponentBase to verify the
> implementation of findComponent.
>
> In general, I *think* the only behavior that is relevant to each unit test
> is the implementation of the method under test.  All other participants in
> that implementation are mocked to control the codepath during execution,
> giving an opportunity to provide 100% codepath coverage over several unit
> tests.
>
> tc,
> -john.
> --
> http://apress.com/book/bookDisplay.html?bID=10044
> Author: Pro JSF and Ajax: Building Rich Internet Components, Apress
>
>


-- 
Matthias Wessendorf
Aechterhoek 18
48282 Emsdetten
blog: http://jroller.com/page/mwessendorf
mail: mwessendorf-at-gmail-dot-com