Munit - Mocking your database calls
One of the more powerful (and in my opinion generally overlooked) aspects of 'modern' software development is the wide range of automated testing options available to us. In the world of automation especially I would hope we might all agree that automated testing is both straightforward (as generally it's message in message out) and so there really is no excuse not to provide at least a basic set of test-cases that exercise your code.
Mule in particular makes this relatively straightforward, using basically components very similar to those that you use to build any other integration. We get a visual display of our test coverage and stand a reasonable chance of being able to cover a reasonable portion of the code-base for not a huge time investment. Really when it comes down to it the only 'hard' part is building repeatable reliable test-cases and where possible remembering that the Unit in MUnit does mean unit testing.
Strictly unit testing 'should' work without external resources, like say databases, because otherwise it's integration-testing. And MUnit does a great job of providing us a way to avoid relying on having a fully configured integration test environment through a Mock Message Processor. This is super-handy as it can mean that we can avoid the pain of spending hours getting connectivity to a shared device (and/or setting up test-data) to locally test a 2-line change before we push to pre-production.
It's not immediately obvious how to mock a database, but if we were to drop a breakpoint on the average database call and see what kind of object the payload is, it turns out to be a simple hashmap or string. So we can use the same basic idea as shown in the link above.
Mocking a string is trivial of course simply set "Then return message with payload:" as the value we want to mock for.
Mocking a more complex resultset type payload really isn't much more complex, we just use MEL to build the structure.
So a resultset from a MS SQL stored procedure call might end up looking somethign like this in the debugger.
resultSet1=[{Actor=William Hartnell , Incarnation=First, Started=1963},{Actor=Sylvester McCoy , Incarnation=Seventh, Started=1987},{Actor=Peter Capaldi , Incarnation=Twelfth, Started=2013}]
... and we can build the same thing in MEL, like this ...
#[ resultSet1:[{"Actor":"William Hartnell","Incarnation":"First","Started":"1963"},{"Actor":"Sylvester McCoy","Incarnation":"Seventh","Started":"1987"},{"Actor":"Peter Capaldi","Incarnation":"Twelfth","Started":"2013"}] ]
slip that into the "Then return message with payload:" and you are good to go.
One tip I was given and it makes a lot of sense, make sure your database calls have unique sensible names. If you are mocking them out it is so much easier to have a direct match on the "And attribute satisfy:" if you can simply use "Name: 'doc:name'" and "Value: '[database call name]'".
Mule in particular makes this relatively straightforward, using basically components very similar to those that you use to build any other integration. We get a visual display of our test coverage and stand a reasonable chance of being able to cover a reasonable portion of the code-base for not a huge time investment. Really when it comes down to it the only 'hard' part is building repeatable reliable test-cases and where possible remembering that the Unit in MUnit does mean unit testing.
Strictly unit testing 'should' work without external resources, like say databases, because otherwise it's integration-testing. And MUnit does a great job of providing us a way to avoid relying on having a fully configured integration test environment through a Mock Message Processor. This is super-handy as it can mean that we can avoid the pain of spending hours getting connectivity to a shared device (and/or setting up test-data) to locally test a 2-line change before we push to pre-production.
It's not immediately obvious how to mock a database, but if we were to drop a breakpoint on the average database call and see what kind of object the payload is, it turns out to be a simple hashmap or string. So we can use the same basic idea as shown in the link above.
Mocking a string is trivial of course simply set "Then return message with payload:" as the value we want to mock for.
Mocking a more complex resultset type payload really isn't much more complex, we just use MEL to build the structure.
So a resultset from a MS SQL stored procedure call might end up looking somethign like this in the debugger.
resultSet1=[{Actor=William Hartnell , Incarnation=First, Started=1963},{Actor=Sylvester McCoy , Incarnation=Seventh, Started=1987},{Actor=Peter Capaldi , Incarnation=Twelfth, Started=2013}]
#[ resultSet1:[{"Actor":"William Hartnell","Incarnation":"First","Started":"1963"},{"Actor":"Sylvester McCoy","Incarnation":"Seventh","Started":"1987"},{"Actor":"Peter Capaldi","Incarnation":"Twelfth","Started":"2013"}] ]
slip that into the "Then return message with payload:" and you are good to go.
One tip I was given and it makes a lot of sense, make sure your database calls have unique sensible names. If you are mocking them out it is so much easier to have a direct match on the "And attribute satisfy:" if you can simply use "Name: 'doc:name'" and "Value: '[database call name]'".
Comments
Post a Comment