|
From: King D. <Ki...@tc...> - 2002-01-30 21:37:39
|
I have a situation where when I construct an object I pass an object to the
constructor that the constructor will call a method on with itself as a
parameter. This is part of a SAX parser and the object being constructed is
a ContentHandler. The object being passed to the constructor is the
XMLReader that the object being constructed is to register itself with.
The constructor looks like this:
public BaseContentHandler( XMLReader reader )
{
this.parentHandler = reader.getContentHandler();
this.reader = reader;
reader.setContentHandler( this );
}
You can see this pattern in the XML parsing code in the Ant project (which
is where I got the idea). Whether this is a good pattern is debatable, but
either way it should be testable.
I created a MockXMLReader object to verify that the constructed object is
setting itself as the content handler. The setContentHandler method calls
setActual on an ExpectationValue. The problem is that I cannot set the
expected value until the constructor returns because I don't have an object
reference until the constructor returns. But the setExpected call does a
clearActual which clears the actual value just set within the constructor.
So I have a problem of which comes first the chicken or the egg or in this
case the expected or the actual. The question is how to solve it and should
Mock Objects be changed to make this easier?
I could subclass ExpectationValue and override clearActual so that
clearActual does nothing, but that is not robust and makes the object not
reusable. I cannot realistically override setHasExpectations which is the
one that is actually calling clearActual because that is the only way to set
the myHasExpectations variable which is private to AbstractExpectation.
One way is to create a wrapper for the expected value to provide an
additional level of indirection. It would look like this (I haven't even
tried to compile this)
public class ExpectationWrapper
{
private Object expected;
public void setExpected( Object expected )
{
this.expected = expected;
}
boolean equals( Object actual )
{
// Should use equals method with check for null
// but you get the idea.
return expected == actual;
}
}
Then my test case would look like:
MockXMLReader reader = new MockXMLReader();
ExpectationWrapper wrap = new ExpectationWrapper();
reader.setExpectedContentHandler( wrap );
wrap.setExpected( new BaseContentHandler( reader ) );
reader.verify();
This strikes me as very kludgey and it seems I should not have to go to such
lengths just because I want to set the actual before the expected. I
understand that usually you want to clear the actual when you set the
expected, but sometimes you don't.
The question boils down to is there any reason why the expected must be set
before the actual? Any thoughts?
--
Dale King
|