Unit testing with Mendix

wessel braakman
Mendix Community
8 min readMar 19, 2020

--

I have been working as a test automation consultant for ANWB through Newspark B.V., meaning that I was responsible for creating and executing test plans, writing Postman scripts and suites, setting up application monitoring, and so on. In October last year, I grew into the role of Mendix developer for a new ANWB project.

Since we started with the new project, Mendix has released an officially supported module with which we can write and execute “unittests”. I’ve put the word unittests between quotes, because under the hood, Mendix uses Java which we can’t/won’t test on that level. The unittests are meant to test the smallest possible (bits of) microflows. Through this blog, I would like to share my experiences with the Unittesting module with you all, so hopefully, you can learn from it.

Prerequisites:

· Some understanding of Mendix

· Mendix Studio Pro 8.x (8.6.1 was used to create this example)

· CommunityCommons v8.2.0

· ObjectHandling v3.0.1

· UnitTesting v8.0

The modules CommunityCommons, ObjectHandling and UnitTesting can be found in the Mendix App Store.

Purpose of this blog:

I have created a simple project to provide some insights into the UnitTesting module. I have not used all aspects of this module in my example, but have instead created a simple, understandable test. So please keep in mind that this is not my best piece of Mendix development, but that this project is meant purely as an example and to inspire others to work with the module.

Domain model

This is what my Domain model looks like:

A single persistable database entity with a Name attribute (string value).

Graphical User Interface (GUI)

My home page consists of a Datagrid, which is linked to the Person object:

My NewEdit page (required to create a new “Person” in the database, or to edit one) is kept simple as well, and has been generated by Mendix:

The “real” page (when running the code through “Run locally”) looks like this:

Microflow

However, behind the “Save” button, there is a microflow. By default, when a NewEdit page is generated, press the “Save” button results in saving any changes without checks. In this case, I do a simple validation within a Microflow, in which I check whether the “Name” attribute is empty or an empty string.

If the “Name” attribute is not filled, the flow goes down, a pop-up is shown with an error message, and nothing is committed (saved). In case the “Name” attribute is filled, the flow continues to the right, changes are committed (saved) and the pop-up is closed.

To keep this example as simple and basic as possible, I chose not to add any further validations, such as a check for duplicates in the database.

UnitTesting

So now we have a database, a GUI for adding and changing names in the database, and a validation flow which checks whether the added/changed name is empty or not. Let’s make a Unittest!

App store modules

For using the UnitTesting module, we need three Mendix App store modules. HEADS-UP! When writing this example I came across a situation that will probably be fixed in the future. After installing the UnitTesting module, an error is shown in our error screen because the module can’t find an icon it’s expecting. This is easily fixed by double-clicking on the error message. You will end up at the element that’s missing an icon, and you can pick a random existing icon from the list to make things work again!

Runtime settings

Besides adding these modules, we need to make a minor change to our project, so the tooling knows which tests we have written. By calling this microflow at the start of our application, the UnitTesting module will search for files that start with Test_ or UT_:

UnitTest Overview

Furthermore, we want to view our unittests on our home screen, so we can run them through our own GUI. I’ve achieved this by adding a container to my page and dragging the “UnitTestOverview” snippet into this container. A snippet is (part of) a page, which you can re-use on other pages. Very handy, because by adding this snippet into my GUI, I don’t have to change or do anything else in order to view and run the tests!

When we run our code once again (Run locally), we should see the UnitTests beneath the Datagrid we already had:

In case you can’t directly see any UnitTests, but you do see the buttons “Run all module tests” and “Reset all tests”, then press the “Reset all tests” button. This will make the tooling look for new tests and will make the tooling find the tests that go with the UnitTesting module (this module comes with a set of example tests). If you like, you can click the “Run all module tests” button. In a blink of an eye, you will see your report appear.

Writing a UnitTest

So, writing our first UnitTest. Our application contains just one microflow with logic; the Validation flow. This flow checks whether the attribute “Name” is filled or not. We can write a test for this.

UnitTest microflow

In the first test, we will write, we call “Test_Validation_No_Name”. We can probably go all-out on naming conventions, but again let’s keep it simple. The most important part here is that the UnitTesting tool checks for microflows that start with “Test_” or “UT_”. So make sure your test microflow name starts with either of those.

Test data

When writing a UnitTest, we want to be in control of the data we use, so in our flow, we create a new “Person” object, WITHOUT a “Name” attribute. Usually, the object is created when we fill in the field on our GUI, but we can work around this by creating an Object in the code:

Submicroflow with logic-under-test

The next step is to drag our Validation microflow into our test microflow. This microflow becomes a block within our testflow, which makes it a sub microflow of our UnitTest:

We should not forget to pass our freshly created “Person” object to the “Validation” microflow. Otherwise, the flow will have no input parameter. We do this by double-clicking on the Validation flow and double-clicking on the Parameter in the config screen. Here we set the value to $NewPerson, our new Object!

Validation

Underneath the “Validation” flow (I made it purple in my flow so we can easily recognize it), we see something called “Variable”, with “Boolean” below it in blue. This is something I prepared in our Validation flow. We can use a Return value in a submicroflow, which can return anything from a string or integer, to an object or list of objects. In this case, I prepared our Validation flow to return a boolean “true” when the “Name” attribute is filled and everything goes as planned. The flow returns a “false” when the “Name” attribute is not filled and we return an error message to the user. We can use this Return value for the assertion in our test:

Alright, we have done a “Create object” action to create a “Person” object WITHOUT a “Name” attribute. Then we enter our purple block, the “Validation” flow. As we can see in the picture above, the Validation flow goes wrong (goes into a fault scenario) when the “Name” attribute is not present. Thus, we expect that the $Variable that returns from the Validation flow is “false”!

We will check this in our test:

Test OK/NOK

Next, I provide the end markers (red dots) of my UnitTest with a “true” or “false” as well, so that the tooling knows whether it should mark my test result GREEN or RED (OK/NOK):

Our own UnitTest in the overview

When we run the code once more (Run Locally), and click the “Reset all tests” button once more, then we should see an extra UnitTest in the overview… The one we just created!

Result

And when we click “Run test”, in the bottom right….

Test passed!

Conclusion

This was a first impression of the UnitTesting tool that is now being offered by Mendix. As I stated at the start of this blog, there are many ways to work with the UnitTesting module. I have kept it simple for now, to keep it readable and understandable for a large public, and I’ve chosen to do my own assertion on the “true” or “false” return value from my Validation microflow. There are two variants of Assertion microflows that come with the UnitTesting module, which I could use for asserting as well. Besides that, I have not used the “ReportStep” microflow that the UnitTesting module offers. This ReportStep can help with debugging because the “Details” screen (right of the “Run test” button) will then show the last passed step before the test failed.

But I can probably talk about those in one of my next blogs.

Would you like to know more about Lowcode development with Mendix, and/or about testing your Mendix application? Don’t hesitate to send me an email on wb@newspark.nl

About me

My name is Wessel Braakman. I’ve been working in/with Test automation since 2012 and work at specialist company Newspark B.V. since 2016. In my current assignment, I got the chance to start working with Mendix as a backend developer and I’m really enjoying myself. My aim is to share knowledge with others and to get others excited about this low-code movement. Hope to see you all at Mendix world, or contact me through e-mail or LinkedIn!

--

--