Writing (unit) tests action, event in Moleculer with Jest
Tags: moleculer, jest, node, microservices
Published: 2023-02-15 16:22:50

## 1. Preface :snowman:
Moleculer is a powerful microservice framework for NodeJs. Because of designed by a microservice architect, we have more than one service responsible for its duty. In order to communicate with other nodes, we can configure transporter like TCP, NATS, Redis transporter, MQTT, AMQP, and Kafka,.. or customize them to be suitable for your business.

Beside design feature to interact with other node, we need to writing unitest for each feature, function inside to it. An aspect of it, we also need to write unitest for action call each other. In this post, I will present a few of my ways to write unitest in this case.

>Note: Please reading about Broker, Transporter, Action, Events concept before reading this post.

![Moleculer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5s0zn1uesynh7533dzme.png)

## 2. Understand about action, event in Moleculer

In the real world, if each of us represents a service so the actions look like the request you need from the other. But we have two cases to request something. First, we request something from others and want the result. Second, we request from others and we do not need or care about their response. 
I have two easy-to-understand examples of these concepts: 
- Bob goes to the market and tells to the cashier, "I want to buy an apple". the cashier checks their stock and sells it to Bob or tells him it's out of stock. Bob will get the response from the cashier. This is the mechanism of actions in moleculer.
- Bob's garbage was full so he leave them in the trash can and he doesn't need to know when they take it out or how to process the rubbish. He just leaves it and goes back to his work. This is the mecahnism of events in moleculer framework.

![Simulation image for communicate](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g7n6nnmsn6mci6b5oos5.jpg)

## 3. How to test action, event

Let's join the main content. Different from testing on the monolithic architecture, each service can be located on a different server and called to another service via the transporter.

In the original document, the example already tests the event called by the action. Based on the moleculer testing document, I have the basic implement test action which calls another action with 3 steps: 
- Mock service broker.
- Create two services (we can load/create/import or create a new service and set test action to this service).

Okay, let's take an overview of the code...

```js
describe("Testing calling actions", () => {
    // Mock service broker
    let broker = new ServiceBroker({ logger: false });

    // set start and stop service 
    beforeAll(() => broker.start());
    afterAll(() => broker.stop());

    // create bob service
    broker.createService({
      name: "bob-service",
      actions: {
        goToMarket(ctx) {
          const buyAppleResponse = ctx.call("cashier-service.sellApple");
          return buyAppleResponse;
        }
      }
    })

    // create cashier service
    broker.createService({
      name: "cashier-service",
      actions: {
        sellApple(ctx) {
          const isAvailableApple = true;
          return isAvailableApple;
        }
      }
    })

    // process test
    describe("Test bob buy apple", () => {
      it("should calling to another action", async () => {
        const viewBobGoToMarket = await broker.call("bob-service.goToMarket");
        console.log(viewBobGoToMarket);
      })
    })
})
```

Logic: 
- First I want to mock a service broker to create an individual environment to run our test.
- Next, I re-build two services corresponding to Bob and Cashier and also create action for each service.
- Process call service via Service Broker to make sure it works.

You can imagine the communication above like this: 

![communication simulation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2lnu7hvi0re0hojeumk.png)

When we replace the actions called with the events, we will not have the response because we don't care about the result or whether the call event lose.


![Event simulation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xh49asyvswpy7nnvhhny.png)

Another way to test an action is to get only the action that we need to test and mock all actions, events, calling to the database,.. inside this test action. The solution depends on your style, business logic, or use context.

## 4. Conclusion
Here is an unitest example when I'm trying to test action with mock action. It's similar when we replace action by event. I think it is simple and hope it easy to understand. I'm new bie in microservice and moleculer framwork, give me an comment if I have any shortcoming. 

Follow me and give me your heart if you're interesting :heart:
Thanks for reading :heart_eyes:

## 5. Reference
- https://moleculer.services/docs/0.14/testing.html