junit-objects Features In Detail

  • Assert an object's state (its properties at a certain point in time) using testing protocols. For instance, the following asserts that an object has isTrue set to true and myString matches the regular expression, "[junit]{4}-[objects]*".

    <object-state name="sampleState">
    	<isTrue>boolean:true</isTrue>
    	<myString>regex:[junit]{4}-[objects]*</myString>
    </object-state>

  • JO greatly reduces the amount of test code in a unit-test by being able to reuse assertion states on any number of objects
  • JO "runtime metaphors" (testXXX methods) let you focus more on application behavior than test code, example:

    @Metaphor
    public final void testMyMetaphor() {
        MyService service = new MyService();
        service.performTask();
    }

    Notice there are no hardcoded assertions or tests in this metaphor. Everything is handled by JO.

  • Assertion Protocols make JO object testing more flexible and powerful. For instance you can easily test that an object has a lazy collection initialized:

    <object-state name="sampleState2">
    	<children>object:instanceof:java.util.Set</children>
    	<children>ognl: not #this['isEmpty']</children>
    </object-state>

    Or, use the other powerful protocols to assert just about anything:

    <object-state>
    
    	asserts that "myObject" is not null
    	<myObject>object:not-null</myObject>
    
    	asserts that "myNumber" == 24
    	<myNumber>ognl:#this >= 15 and (#this / 8) == 3</myNumber>
    
    	tests if "myCollection" contains the String "happy"
    	<myCollection>ognl:"happy" in #this</myCollection>
    
    </object-state>

  • JO allows testing of state transitions. When an object changes state, you can assert that the change is deterministic and well-behaved. The following asserts that an object starts out with state "sampleState1" and then transitions (changes properties) to "sampleState2" whenever a method is called (this can be very useful in testing modes, or steps in a wizard, for instance):

    <state-chain>
    	<!-- The next state is asserted on "Wizard.nextStep()" -->
    	<trigger method="nextStep" class="Wizard"/>
    
    	<state refid="sampleState1"/>
    	<state refid="sampleState2"/>
    	<state refid="sampleState3"/>
    
    	<!-- etc. -->
    
    </state-chain>

  • JO supports flexible conditional triggering (for instance, only assert that a collection contains item A when it has more than 5 items)
  • JO supports profiling of "design states". This means you can assert design patterns on objects and their relationships easily. For example:

    <!-- asserts "com.MyType" as a flyweight pattern -->
    <object-profile>
    	<design-pattern>core:flyweight</design-pattern>
    
    	<class>com.MyType</class>
    </object-profile>
    
    <!-- asserts an adapter design pattern -->
    <object-profile>
    	<design-pattern>core:adapter</design-pattern>
    
    	<class>service:MyProducer</class>
    	<class>adapter:MyAdapter</class>
    	<class>client:MyConsumer</class>
    </object-profile>
    
    <!-- asserts that "SomethingHelper" is NOT anemic -->
    <object-profile>
    	<anti-profile/>
    
    	<design-pattern>anti-pattern:anemic-object</design-pattern>
    	<class>SomethingHelper</class>
    </object-profile>

  • Use JO Profiling to root out design entropy (i.e. where a set of objects may benefit from using a design pattern):

    <entropy-profile>
    	<anti-profile/>
    	<search-pattern>entropy:constructor-clutter</search-pattern>
    
    	<class>server:com.mydomain.MyService</class>
    	<class>user:com.mydomain.clients.*</class>
    <entropy-profile>


Things to know about JO

  • JO makes use of runtime reflection
  • JO instruments classes by injecting bytecode (using the javassist library) and rewriting .class files. Never use JO-instrumented binaries in production (duh)
  • JO runtime metaphors do not support multithreading (yet)
  • You may need to set ReflectionPolicy "suppressAccessChecks" in your JRE's security policy file if you want JO to inspect restricted members (private, protected, etc.) of classes. This is usually set by default in most JREs and JDKs anyway
  • Placing multiple metaphors that SHARE trigger methods in the same ObjectTestCase is not recommended (however you can freely use the same trigger methods on any number of state-chains or profiles within the same metaphor)
  • Do NOT run an ObjectTestCase with junit =), though I hope to have junit UI integration sometime in the future
  • JO instruments bytecode on the filesystem, therefore it should affect all classloaders so long as they are run within a JO metaphor
  • JO may not work as expected with AspectJ or other AOP frameworks (let me know if you are successul!)

What JO is not

  • JO is not a performance profiler
  • JO is not a design tool
  • JO is not an extension/version/plugin to junit (in fact JO has nothing to do with junit beyond the name)

Planned Future Improvements

  • Profiling and state assertion of EJBs
  • Realtime metaphors (running unit-tests and object-profiles in a fully-deployed, J2EE application)
  • Multi-threaded runtime metaphors
  • Ant task/GUI integration for running tests

GetJava Download Button
SourceForge.net Logo
Support This Project