Announcement Announcement Module
Collapse
No announcement yet.
Unit Testing Expression based components Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Unit Testing Expression based components

    Any day I can remove code is a good day so I am excited to start moving our simpler message processors to use expressions instead of java methods. However, I am finding it difficult to unit test them. With the explicit java filters/routers/transformers/etc the unit tests are nicely isolated to the ref'd method with no wiring or mocks. When using expressions instead the expression should still be tested but isolated from the ExpressionEvaluatingFilter/Router/Transformer/etc.

    What if the following interface was added

    Code:
    public interface ExpressionEvaluatingComponent {
    
    	Expression getExpression();
    
    }
    Then all relevant message processing components could implement this so unit tests like the following could be written.

    Code:
    @ContextConfiguration
    @RunWith(SpringJUnit4ClassRunner.class)
    public class PriorityRouterTest {
    
    	@Autowired
    	@Qualifier("priorityRouter")
    	private ExpressionEvaluatingComponent priorityRouter;
    
    	@Test
    	public void testRouter() {
    		Message<String> lowestPriority = MessageBuilder.withPayload("foo").setPriority(1).build();
    		...
    		Message<String> higestPriority = MessageBuilder.withPayload("baz").setPriority(9).build();
    
    		Expression expression = priorityRouter.getExpression();
    		assertEquals("StandardPriorityChannel", expression.getValue(lowestPriority));
    		assertEquals("HighPriorityChannel", expression.getValue(highestPriority));
    	}
    }
    Is there an easier way? I dont see any way to get the expression otherwise except by using an xpath against the config xml.

  • #2
    Interesting thought, but why not just make this an integration test and send a message through (part of) the system?

    The chances of a bug in the framework code are rather small and if your logic is so complex that it should be isolated from the configuration, you should do just that.

    Comment


    • #3
      My point is that if I had used a method instead of an expression I could write a simple, fast, isolated unit test. All I would have to do is inject the bean and call the method to test it. However by using the expression I have to write a more complex integration test.

      Comment


      • #4
        I agree with your point. In fact, I usually point this out as one of the tradeoffs; expressions might simplify and add flexibility, but referencing a POJO that is also unit-tested in isolation adds some peace of mind. I often point out that if the expression is complex enough that you feel it should be tested, then perhaps you should instead be relying on a POJO anyways. Of course, that's where subjectivity enters the picture. People have different thresholds for what they consider complex enough to require test coverage. Anyone who has accidentally flipped a less-than/greater-than sign (myself included ) might tend toward the side of caution.

        Iwein does raise an important point though. The ability to perform an "integration" test over part of a message flow is really helpful for those high-level "sanity" checks when you do add expression support within the flow.

        One final suggestion that I'd like to offer - more as a compromise - is that you could use placeholders for the actual expressions. For example, you could store the actual expressions in a properties file. Then, you could write unit tests that load those same expressions and execute them with various input values while asserting the expected evaluation results.

        HTH,
        Mark

        Comment

        Working...
        X