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 <[EMAIL PROTECTED]> wrote:
On 5/14/06, Adam Winer <[EMAIL PROTECTED]> wrote:
>
> On 5/14/06, John Fallows <[EMAIL PROTECTED]> wrote:
> > On 5/13/06, Craig McClanahan <[EMAIL PROTECTED]> 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

Reply via email to