Re: DNA TCK?

Leo Simons <[email protected]> Fri, 16 Jan 2004 12:43:36 +0100
Newsgroups gmane.comp.java.jcontainer.interest
Message-ID <[email protected]>
Chad Woolley wrote:
> Leo Simons wrote:
>> If not, things can still proceed but it's a lot of manual labor :/
> 
> Hi Leo,

Hya!

> I just joined this list for reasons pretty unrelated to IoC containers, 
> but coincidentally, I might be able to provide some help.

I just love coincidences like that :D

> I'll admit I'm not fully sure what you are trying to do, but it looks 
> like you are basically trying to verify that a given method was invoked, 
> even if you don't have control over all the entry points.

yep.

I have a method A inside a class C, and I want to be able verify it was 
invoked once, twice, or n times, with what arguments, wheter it was 
invoked before or after or at the same time as method B, etc etc. I will 
also want to know at what time methods A and B were invoked, and how 
long their invocation took.

Note this is different from what something like EasyMock or DynaMock 
(AIUI) does: I want to provide an implementation class (ie an actual 
.class file) to a container, then take a look at what the container does 
with it at runtime.

> You might want to check out my project, VirtualMock 
> (http://www.virtualmock.org), as it is designed to do exactly this.

Looking at it now. It seems to do what I want. Shame I didn't read your 
original post...I would've probably tried it first :D

> It is based on AOP, so it may have some of the problems that you 
> mention. However, I do support both major AOP implementations (AspectJ 
> and AspectWerkz).  Between them, they support several approaches to the 
> two basic types of bytecode modification (post-compilation, and class 
> loader manipulation).
> 
> In VirtualMock, I've dealt with some of the issues you mention - by 
> that, I mean the general problem of AOP bytecode manipulation 
> interfering with other tools/applications.  However, when you drill down 
> to the specific problem, it can often be overcome, especially if you 
> have the choice of switching between the post-compile vs. classloader 
> approach, without affecting the functionality of your framework.  
> VirtualMock is designed to allow just this.  Also, the folks at 
> AspectWerkz are very committed to fixing this type of incompatibility if 
> it is fixable.

I just have a lot of scepticism to overcome here. If I use 
VirtualMock+AspectWerkz to create mocks that I put inside an environment 
that modifies the mocks using AspectJ (or the other way around), will it 
work? Have you tried things like that? Has anyone? Will it still work 6 
months from now?

What about a container that uses java proxies, or worse, a custom 
BCEL-based or CGLIB-based proxy generator? (ie,

http://cvs.apache.org/viewcvs.cgi/*checkout*/avalon/fortress/container/src/impl/org/apache/avalon/fortress/impl/factory/BCELWrapperGenerator.java?content-type=text%2Fplain&rev=1.12
http://cvs.apache.org/viewcvs.cgi/*checkout*/avalon/fortress/container/src/impl/org/apache/avalon/fortress/impl/factory/BCELCodeGenerator.java?content-type=text%2Fplain&rev=1.6

)

Not that I place any more trust in being able to combine those with my 
custom java-proxy based code, but when errors occur there I'll have a 
rather short and familiar stack trace to look at.

> Also, I am also planning to support dynamic-proxy based mocking in the 
> future, which may be a viable third alternative in some situations, but 
> this is not implemented yet and is probably a more long term.

that won't help me...see above :D

> As I mentioned in my other thread asking for IoC advice, I think that 
> virtual mocks are a powerful concept, which have many potential uses 
> that have not been considered yet.  This may be one of them.
> 
> In any case, it looks like the VirtualMock framework could save you some 
> work in your project, or maybe not.  I'm very committed to making 
> VirtualMock as flexible as possible for any use, not just Unit Testing.  
> So, I'll be very receptive to any suggestions you have on how to make it 
> more flexible, or any specific problems you have with using it.  It's 
> still in alpha and evolving, but the core functionality is all there and 
> working.

I'm definately going to try it out at some point. For reference, here's 
a sample of what I would want to do with VirtualMock (currently not 
knowing much about its api):

                                                            // fragments
public abstract class AbstractContainerTestCase
   extends AbstractMockTestCase
{
   public MockService m_mockService;

   public void setUp() throws Exception
   {
     super.setUp();

     m_mockService = super.getMockService();
   }

   public abstract Homer getHomer(); // implemented in subclass;
     // by contract the created instance must be a subclass of
     // AbstractHomer, which is supplied by the TCK. How the
     // subclass creates the instance, or exactly what happens to it...
     // I don't know, but I want to take a look at what happened later

   public void testHomerCreatedAsHeShouldHaveBeen()
   {
     final Homer homer = getHomer();
     final Recorder recorder = m_mockService.getRecorder( homer );

     assertNoExceptionsWereThrown( recorder );
     assertWasFirstMethodCall( recorder, "setMarge" );
     assertNoNullArguments( recorder, "setMarge" );
     assertWasMethodCallNumberInRange( 0, 5, recorder, "setBart" );
     assertNoNullArguments( recorder, "setBart" );
     assertWasLastMethodCall( recorder, "initialize" );
     assertWasNotCalled( recorder, "setSomeoneFamous" );

   }
}

Those assertions would take a look at what the recorder recorded, and 
fail with meaningful error messages. An example would be:

assertNoExceptionsWereThrown( Recorder recorder )
{
   Invocation[] invocations = recorder.getRecordedInvocations();
   for( int i = 0; i < invocations.lengthl i++ )
   {
     Throwable t = invocation.getThrowable();
     if( t != null )
     {
       t.printStackTrace();
       fail(
         "we recorded that the method " + invocation.getMethod() +
         " of the " + invocation.getTarget().getClass().getName() +
         " instance your provided threw an exception: "
         + t.getMessage() );
     }
   }
}

I guess most of these methods are pretty domain-specific.

> Anyway, just thought I'd mention it since it seems like VirtualMock 
> might be able to help you.  Let me know!

will do. You want further feedback on this list or somewhere else?

-- 
cheers,

- Leo Simons

-----------------------------------------------------------------------
Weblog              -- http://leosimons.com/
IoC Component Glue  -- http://jicarilla.org/
Articles & Opinions -- http://articles.leosimons.com/
-----------------------------------------------------------------------
"We started off trying to set up a small anarchist community, but
  people wouldn't obey the rules."
                                                         -- Alan Bennett