Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Using AspectJ and mock objects--again

Apologies: I hit send in the middle of my last email. Here's the complete
answers:

Keith,

Glad you liked my article. <plug>You should also check out my book:
Mastering AspectJ.</plug>

In answer to question 1: I can't tell by inspection what might be going
wrong. I suggest using either AJDT or AjBrowser to see if your pointcuts are
accidentally advising anything you don't mean them to. You can also print
information from thisJoinPoint in your advice to get a better idea of where
the advice is executing.

In answer to question 2: Method level overrides are verbose in AspectJ, so I
agree that swapping in a traditional mock object is preferable.
Unfortunately, it's impossible to use AspectJ to replace a constructor join
point unless the replacement returns a subtype of the originally constructed
object. Fortunately for you, your mock does subclass your original object.
Therefore, you can use around advice on the constructor call join point to
replace "new MyDAO()" with "new MockDAO()".

It's worth mentioning that often there are opportunities for refactoring in
situations like this. Passing the DAO into the collaborator from client code
allows real clients to alter the collaborator's behavior in well-defined
ways. Of course, there are situations where this is undesirable. (Hence my
article.)

Hope I've helped,
Nick



On 7/31/03 12:25 PM, "SADER, KEITH D (Contractor)" <KEITH.D.SADER@xxxxxxxx>
wrote:

> Hi, I'm trying to use aspects to mock 'on the fly' a domain layer class.  I've
> tried to follow Nicholas Leseicki's great article at
> http://www-106.ibm.com/developmerworks/java/library/j-aspect2.  I've had some
> luck, but I'm getting  some unexpected behavior.
> 
> My aspect looks like this - real names replaced to protect the innocent.
> 
> import java.util.Collection;
> // import other stuff
> 
> public aspect DAOAspect
> {
>   pointcut inTest() : execution(public void MyTestCase.*());
>   pointcut findThings(String searchStr) :
>       cflow(inTest()) &&
>       call(Collection MyDAO.find*(*)) && // MyDAO is a concrete class, not an
> interface.
>       !call(Collection MockMyDAO.find*(*)) &&
>       args(searchStr);
> 
>   Collection around(String searchStr) : findThings(searchStr)
>   {
>       System.out.println("In the aspect");
>       System.out.println("searchStr is : " + searchStr);
>       return new MockMyDAO().findStuff(searchStr);
>   }
> }
> 
> First bit of unexpected behavior:
> I see that my aspect is called twice via the System.out.println()s
> "In the aspect"
> "search"
> "In the aspect"
> "search"
> ...
> 
> Why would this happen?  I believe I'm only calling into the mocked DAO once.
> // test case
> public void testFind()
> {
>   assertTrue(0 < daoCollaborator.find("search"));
> }
> 
> // code under test in DAOCollaborator
> public Collection find(String searchStr)
> {
>   return new MyDAO().findStuff(searchStr);
> }
> 
> // MyMockDAO over-ride
> public Collection findStuff(String searchStr)
> {
>  return mockStuff;
> }
> 
> Second question/behavior.
> Is it possible for me to just return the MockDAO whenever the DAO is
> invoked/used?  It would make it easier for me to just return the mock object
> reference instead of having the aspect return method level items.  I'm not
> clear on the syntax/advice I need to  use to do this.
> 
> thanks,
> ---
> Keith Sader
> Nash Resources Group sub-contracting for Computer Sciences Corporation
> IAD:TFAS
> Email:keith.d.sader@xxxxxxxx
> We've got a blind date with destiny, and it looks like she ordered the
> lobster.
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> http://dev.eclipse.org/mailman/listinfo/aspectj-users



Back to the top