Indianapolis MuleSoft Meetup Group
Effective Unit Testing in MuleSoft
2
Organizer
Ikram Mohamed
Integration Associate
@OneAmerica
About the organizer:
 Working as Integration Associate at OneAmerica.
 Indianapolis MuleSoft Meetup Leader & Mentor.
 15+ Years of I.T Experience
 Certified MuleSoft Integration Developer and
Platform Architect.
Speaker
3
Josh Erney
MuleSoft Ambassador
About me
● MuleSoft Ambassador
● Developing/Architecting MuleSoft solutions ~5 years
● Typically approach software development from a financial & long-term maintainability
standpoint
○ “If you want to go fast, do it right”
4
About me
● MuleSoft Ambassador
● Developing/Architecting MuleSoft solutions ~5 years
● Typically approach software development from a financial & maintainability standpoint
○ “If you want to go fast, do it right”
● 2 Dogs - Eddie, Bennie
● Wrote the tutorial for the DataWeave Playground
● Wrote half of a book on DataWeave, once
5
Effective Unit Testing in MuleSoft
5 Steps
1. Understand the value of unit tests
2. Assert your code meets interface contracts
3. Write testable code
4. Remove the noise
5. Valuable tests first, code coverage second
7
Where did these steps come from
A lot of code reviews over the last year. What I found:
● Despite overall increases in code quality, tests were still lacking. Knowing how to write
maintainable source code doesn’t immediately translate to knowing how to write good tests.
● Developers were writing unit tests because they were required to, but the tests were weak.
● Code was passing automated build/deploy processes, but still had logic bugs when sent to QA
● Code coverage was high, but test quality was bad.
● After speaking with developers, I learned most didn’t understand the value of unit tests, and
therefore did not know how to create valuable tests.
● Ultimately: just having unit tests isn’t enough. Having poorly designed unit tests robs us of
productivity and increases maintenance costs.
8
Talk Objectives
I’d like you to walk away from this presentation able to:
● Describe why we write unit tests
● Identify high-value test cases within your code
● Understand how to write high-value tests
● Write testable code, refactor non-testable code into testable code
● Understand why we need to be thoughtful when using the test recorder
9
Keep the end goal in mind
1) Understand the Value of Unit Tests
Why do we create unit tests? What
makes them valuable?
The value of unit tests
● May increase code quality (maintenance costs ⬇️, dev velocity ⬆️)
● May enable developers to confidently refactor (maintenance costs ⬇️, dev velocity ⬆️)
● May enable developers to confidently add new features without introducing regressions
(maintenance costs ⬇️, dev velocity ⬆️)
● May reduce quantity of bugs (maintenance costs ⬇️, dev velocity ⬆️)
● May serve as a form of documentation (maintenance costs ⬇️, dev velocity ⬆️)
12
The value of unit tests
● May increase code quality (maintenance costs ⬇️, dev velocity ⬆️)
● May enable developers to confidently refactor (maintenance costs ⬇️, dev velocity ⬆️)
● May enable developers to confidently add new features without introducing regressions
(maintenance costs ⬇️, dev velocity ⬆️)
● May reduce quantity of bugs (maintenance costs ⬇️, dev velocity ⬆️)
● May serve as a form of documentation (maintenance costs ⬇️, dev velocity ⬆️)
Tests are for “future you”, and developers who may need to modify your code in the future.
13
Trivia 1
What is one of the benefits of writing valuable unit tests?
A. Makes your boss happy
B. May reduce maintenance costs
C. Better code coverage
D. May eliminate all bugs from your application
14
2) Assert Code Meets Interface Contracts
Assert code meets interface contracts
● Given inputs “x”, are calls to dependent APIs correct?
○ If synchronous API, is response correct (body and HTTP status code)?
● Test should fail if code does not meet interface expectations
○ i.e. “Payload is not null” is almost never enough
● Test of this type should never be viewed as optional
● Flows and subflows have interfaces, too!
16
Example: Asserting Code Meets Interface
Requirements
3) Write Testable Code
What makes code testable?
● “Testable” is a spectrum
○ You shouldn’t need to mock 10 different components
● Code that is thoughtfully organized into flows/sub-flows
○ Bias towards code organization that reflects how you would communicate about the code
■ “This flow gets data from system x, collects associated data from system y, then groups the data and sends
it to a queue”
● Values that need to be tested must be visible for testing
● Testable code is deterministic. Avoid using now() and random() within DW scripts. These
functions are non-deterministic.
○ We often need to use now(), how can we set up our source code and test to make this code
testable?
19
Trivia 2
What is a good indicator of testable software?
A. Good naming conventions
B. The software already has a lot of tests
C. The software tests provide great code coverage
D. Non-deterministic values are extracted into mockable variables
20
Example: Making our code testable
4) Eliminate the Noise
Eliminate the noise
23
● Noise is code or a test that cannot be linked back to a requirement or interface contract
● Noise could also be a test that doesn’t assert anything useful
● Noise ends up increasing maintenance costs instead of decreasing them
○ Noise creates confusion, “Why is this test making assertions about data that are not used by the
flow?”
● The MUnit Test Recorder can create a lot of noise, be thoughtful when using it! (more on this
later)
Demo - Munit Test Recorder
The Good
● Quickly create test cases
● Probably great code coverage if you
record every flow
Thoughts about the Test Recorder
25
The Bad
● Easier to create noise (e.g. forgetting not to mock
unnecessary attributes, mocking payloads with
100s of records)
● Poor file naming for things like mock payloads
● Cannot mock and spy the same component
● Mock data is always in application/dataweave
format
● File generation clutters src/test/resources
5) Valuable Tests First, Code Coverage
Second
Valuable Tests First, Code Coverage Second
● Code coverage can be a misleading metric for software quality
● Write your high-value tests first, check if code coverage criteria is met, then add more if
necessary
● Code reviews should be exposing weak tests
○ Helps mitigate developers aiming for code coverage instead of high-value tests
27
Other tips
28
● Unit tests should not be dependent on use of the network or file system
● More complex code should probably have more robust tests
● Tests should function as a form of documentation. Expected inputs to flows & dependent
systems, as well as expected outputs
● Test all paths. Generally flows with choice routers require 1 test per possible path. This
includes exceptions.
● Testing DataWeave code: Often times it’s not necessary, your interface tests should expose
bugs in transformation logic. DataWeave is an implementation detail.
● Never mock on doc:id alone, always include at least the doc:name
● Never trust a test that you haven’t seen fail
Trivia 3
When writing unit tests, why should you focus on writing valuable tests first, and code coverage
second?
A. Without valuable tests, code coverage is meaningless
B. Code coverage isn’t that important
C. Valuable tests are difficult to write, so we should approach them with a fresh mind
D. An authority figure said so in an online presentation
29
Example: MUnit Test Recorder
Questions?

Indy meetup#7 effective unit-testing-mule

  • 1.
    Indianapolis MuleSoft MeetupGroup Effective Unit Testing in MuleSoft
  • 2.
    2 Organizer Ikram Mohamed Integration Associate @OneAmerica Aboutthe organizer:  Working as Integration Associate at OneAmerica.  Indianapolis MuleSoft Meetup Leader & Mentor.  15+ Years of I.T Experience  Certified MuleSoft Integration Developer and Platform Architect.
  • 3.
  • 4.
    About me ● MuleSoftAmbassador ● Developing/Architecting MuleSoft solutions ~5 years ● Typically approach software development from a financial & long-term maintainability standpoint ○ “If you want to go fast, do it right” 4
  • 5.
    About me ● MuleSoftAmbassador ● Developing/Architecting MuleSoft solutions ~5 years ● Typically approach software development from a financial & maintainability standpoint ○ “If you want to go fast, do it right” ● 2 Dogs - Eddie, Bennie ● Wrote the tutorial for the DataWeave Playground ● Wrote half of a book on DataWeave, once 5
  • 6.
  • 7.
    5 Steps 1. Understandthe value of unit tests 2. Assert your code meets interface contracts 3. Write testable code 4. Remove the noise 5. Valuable tests first, code coverage second 7
  • 8.
    Where did thesesteps come from A lot of code reviews over the last year. What I found: ● Despite overall increases in code quality, tests were still lacking. Knowing how to write maintainable source code doesn’t immediately translate to knowing how to write good tests. ● Developers were writing unit tests because they were required to, but the tests were weak. ● Code was passing automated build/deploy processes, but still had logic bugs when sent to QA ● Code coverage was high, but test quality was bad. ● After speaking with developers, I learned most didn’t understand the value of unit tests, and therefore did not know how to create valuable tests. ● Ultimately: just having unit tests isn’t enough. Having poorly designed unit tests robs us of productivity and increases maintenance costs. 8
  • 9.
    Talk Objectives I’d likeyou to walk away from this presentation able to: ● Describe why we write unit tests ● Identify high-value test cases within your code ● Understand how to write high-value tests ● Write testable code, refactor non-testable code into testable code ● Understand why we need to be thoughtful when using the test recorder 9
  • 10.
    Keep the endgoal in mind 1) Understand the Value of Unit Tests
  • 11.
    Why do wecreate unit tests? What makes them valuable?
  • 12.
    The value ofunit tests ● May increase code quality (maintenance costs ⬇️, dev velocity ⬆️) ● May enable developers to confidently refactor (maintenance costs ⬇️, dev velocity ⬆️) ● May enable developers to confidently add new features without introducing regressions (maintenance costs ⬇️, dev velocity ⬆️) ● May reduce quantity of bugs (maintenance costs ⬇️, dev velocity ⬆️) ● May serve as a form of documentation (maintenance costs ⬇️, dev velocity ⬆️) 12
  • 13.
    The value ofunit tests ● May increase code quality (maintenance costs ⬇️, dev velocity ⬆️) ● May enable developers to confidently refactor (maintenance costs ⬇️, dev velocity ⬆️) ● May enable developers to confidently add new features without introducing regressions (maintenance costs ⬇️, dev velocity ⬆️) ● May reduce quantity of bugs (maintenance costs ⬇️, dev velocity ⬆️) ● May serve as a form of documentation (maintenance costs ⬇️, dev velocity ⬆️) Tests are for “future you”, and developers who may need to modify your code in the future. 13
  • 14.
    Trivia 1 What isone of the benefits of writing valuable unit tests? A. Makes your boss happy B. May reduce maintenance costs C. Better code coverage D. May eliminate all bugs from your application 14
  • 15.
    2) Assert CodeMeets Interface Contracts
  • 16.
    Assert code meetsinterface contracts ● Given inputs “x”, are calls to dependent APIs correct? ○ If synchronous API, is response correct (body and HTTP status code)? ● Test should fail if code does not meet interface expectations ○ i.e. “Payload is not null” is almost never enough ● Test of this type should never be viewed as optional ● Flows and subflows have interfaces, too! 16
  • 17.
    Example: Asserting CodeMeets Interface Requirements
  • 18.
  • 19.
    What makes codetestable? ● “Testable” is a spectrum ○ You shouldn’t need to mock 10 different components ● Code that is thoughtfully organized into flows/sub-flows ○ Bias towards code organization that reflects how you would communicate about the code ■ “This flow gets data from system x, collects associated data from system y, then groups the data and sends it to a queue” ● Values that need to be tested must be visible for testing ● Testable code is deterministic. Avoid using now() and random() within DW scripts. These functions are non-deterministic. ○ We often need to use now(), how can we set up our source code and test to make this code testable? 19
  • 20.
    Trivia 2 What isa good indicator of testable software? A. Good naming conventions B. The software already has a lot of tests C. The software tests provide great code coverage D. Non-deterministic values are extracted into mockable variables 20
  • 21.
    Example: Making ourcode testable
  • 22.
  • 23.
    Eliminate the noise 23 ●Noise is code or a test that cannot be linked back to a requirement or interface contract ● Noise could also be a test that doesn’t assert anything useful ● Noise ends up increasing maintenance costs instead of decreasing them ○ Noise creates confusion, “Why is this test making assertions about data that are not used by the flow?” ● The MUnit Test Recorder can create a lot of noise, be thoughtful when using it! (more on this later)
  • 24.
    Demo - MunitTest Recorder
  • 25.
    The Good ● Quicklycreate test cases ● Probably great code coverage if you record every flow Thoughts about the Test Recorder 25 The Bad ● Easier to create noise (e.g. forgetting not to mock unnecessary attributes, mocking payloads with 100s of records) ● Poor file naming for things like mock payloads ● Cannot mock and spy the same component ● Mock data is always in application/dataweave format ● File generation clutters src/test/resources
  • 26.
    5) Valuable TestsFirst, Code Coverage Second
  • 27.
    Valuable Tests First,Code Coverage Second ● Code coverage can be a misleading metric for software quality ● Write your high-value tests first, check if code coverage criteria is met, then add more if necessary ● Code reviews should be exposing weak tests ○ Helps mitigate developers aiming for code coverage instead of high-value tests 27
  • 28.
    Other tips 28 ● Unittests should not be dependent on use of the network or file system ● More complex code should probably have more robust tests ● Tests should function as a form of documentation. Expected inputs to flows & dependent systems, as well as expected outputs ● Test all paths. Generally flows with choice routers require 1 test per possible path. This includes exceptions. ● Testing DataWeave code: Often times it’s not necessary, your interface tests should expose bugs in transformation logic. DataWeave is an implementation detail. ● Never mock on doc:id alone, always include at least the doc:name ● Never trust a test that you haven’t seen fail
  • 29.
    Trivia 3 When writingunit tests, why should you focus on writing valuable tests first, and code coverage second? A. Without valuable tests, code coverage is meaningless B. Code coverage isn’t that important C. Valuable tests are difficult to write, so we should approach them with a fresh mind D. An authority figure said so in an online presentation 29
  • 30.
  • 31.