Published by Manuel Rivero on 04/08/2022
Learning, Contract Testing, Role Testing, Testing, Object-Oriented Design, Polymorphic Testing, Integration Testing, Design Patterns
Similar to what we did in our previous example of role tests in Java, we wrote the following tests to develop two different implementations of the
TransactionsRepository port while solving the Bank Kata: the
InMemoryTransactionsRepository and the
These are their tests, respectively:
As what happened in our previous post, both tests contain the same test cases since both tests document and protect the contract of the same role,
Again we’ll use the concept of role tests to remove that duplication, and make the contract of the role we are implementing more explicit.
Although Jest does not have something equivalent or similar to the RSpec’s shared examples functionality we used in our previous example in Ruby, we can get a very similar result by composing functions.
First, we wrote the
behavesLikeATransactionRepository function. This function contains all the test cases that document the role and protect its contract, and receives as a parameter a
testContext object containing methods for all the operations that will vary in the different implementations of this integration test.
Notice that in the case of Jest we are using composition, whereas we used inheritance in the case of Junit.
Then, we called the
behavesLikeATransactionRepository function from the previous tests and implemented a particular version of the methods of the
testContext object for each test.
This is the new code of
And this is the new code of
NodePersistTransactionRepository after the refactoring:
This new version of the tests not only reduces duplication, but also makes explicit and protects the behaviour of the
TransactionsRepository role. It also makes less error prone the process of adding a new implementation of
TransactionsRepository because just by using the
behavesLikeATransactionRepository function, you’d get a checklist of the behaviour you need to implement in order to ensure substitutability, i.e., to ensure the Liskov Substitution Principle is not violated.
These role tests using composition are also more readable than the Junit ones, in my opinion at least :)
I’d like to thank Audiense’s deliberate practice group for working with us on this kata, and my colleague Rubén Díaz for co-facilitating the practice sessions with me.
Thanks to my Codesai colleagues for reading the initial drafts and giving me feedback, and to Elina Sazonova for the picture.
- Role tests for implementation of interfaces discovered through TDD, Manuel Rivero
- Example of role tests in Java with Junit , Manuel Rivero
- Liskov Substitution Principle
Photo from Elina Sazonova in Pexels
Originally published in Manuel Rivero's blog.