<!-- .slide: style="font-size: 30px;" -->
# Testing microservices: Part 2
## CH. 10
---
<!-- .slide: style="font-size: 30px;" -->
## Agenda
- Test pyramid (CH.9)
- Unit tests (CH.9)
- Integration tests (10.1)
- Component tests (10.2)
- End-to-end tests (10.3)
---
<!-- .slide: style="font-size: 30px;" -->
## Test pyramid (CH.9)

Note:
下到上:越下面越多
左邊:測試目的
右邊:特性
- 測試 & 獲得回饋的速度
- 可靠的程度
- 花費的時間 & 人力成本
---
<!-- .slide: style="font-size: 25px;" -->
## Unit tests (CH.9)

- 目標:Test business logic
- 方法:Verify unit (class, function) behaves as expected
- 面向:Technology-facing tests that support development
Note:
- sociable unit test (business logiic)
- test class and its dependencies
- entity: test order.getOrderTotal() is correct
- value object: test Monet object can be added
- saga: test saga send the correct command message
- solitary unit test
- test a class in isolation
- controller、service、adapter:mock their dependencies, Verifies that the value returned by the service method is correct and that the dependencies have been invoked correctly
----
<!-- .slide: style="font-size: 25px;" -->
### Sociable unit test & Solitary unit test

Note:
- sociable unit test (business logiic)
- test class and its dependencies
- entity: test order.getOrderTotal() is correct
- value object: test Monet object can be added
- saga: test saga send the correct command message
- solitary unit test
- test a class in isolation
- controller、service、adapter:mock their dependencies, Verifies that the value returned by the service method is correct and that the dependencies have been invoked correctly
---
<!-- .slide: style="font-size: 25px;" -->
## Integration tests

- 目標:Verify a service can properly interact with other services/infrastructure
- 方法:Test the individual adapter classes that implement the communication
- 面向:Technology-facing tests that support development (between services)
----
<!-- .slide: style="font-size: 25px;" -->
### Order Service Example

- Strategy 1: test service's adapters
- Strategy 2: use contracts to veriyfy interactions between applications
Note:
先講 strategy,再講圖
----
<!-- .slide: style="font-size: 30px;" -->
### Persistence integration tests
- Test interaction with DB
- Directly tests the OrderRepository class
- Setup (docker) > Execute > Verify > Teardown

Note:
Rather than test persistence through Order Service’s API, it directly tests the OrderRepository class
- different: The unit tests we wrote earlier only test in-memory objects
- steps:
- setup
- execute
- verify
- teardown
----
<!-- .slide: style="font-size: 30px;" -->
### Contract tests (CH.9)
- Verify Service (provider) and its Client (consumer) can communicate
- If both are tested with the same contracts:
- Provider and Consumer can communicate
- Testing them **in isolation**


Note:
- client vs provider (判斷誰是誰)
- Consumer-side:
- tests consumer’s adapter.
- simulate provider res/output
- verify can call provider corectlly
- Provider-side:
- tests provider’s adapter.
- simulate consumer req/input
- test the adapters call its dependencies corectlly
- consumer-driven contract: 由 consumer 撰寫
- 取代聯調?
----
<!-- .slide: style="font-size: 30px;" -->
#### Order Service Example


----
<!-- .slide: style="font-size: 30px;" -->
#### Contract for REST API

- Provider: Verify OrderController can handle this endpoint and generate the expected response
- Consumer: Invokes OrderServiceProxy and verifies that either it returns the correct values or throws the expected exception
----
<!-- .slide: style="font-size: 30px;" -->
#### Contract for publish/subscribe interactions

- Provider: Invokes OrderDomainEventPublisher to publish an OrderCreated event and verify it match clients’ expectations
- Consumer: Verify OrderHistoryEventHandlers invokes its dependencies correctly
----
<!-- .slide: style="font-size: 30px;" -->
#### Contract for asyncrequest/response interactions

- Provider: Invokes KitchenServiceCommandHandler and verifies the reply message is correct
- Consumer: Invokes KitchenServiceProxy and verifies that it returns the expected result
---
<!-- .slide: style="font-size: 30px;" -->
## Component tests

- 目標:Acceptance test for service
- 方法:Tests a service in isolation by using stubs for its dependencies
- 面向:Business-facing tests for a software component
Note:
which treat it as a black box and verify its behavior through its API.
測試可以滿足 use case
----
<!-- .slide: style="font-size: 30px;" -->
### Designing component tests

- In-process: runs the service with in-memory stubs and mocks for its dependencies
- Out-of-process: test uses real infrastructure services (db, message brokers) but uses stubs for any dependencies that are application services
----
<!-- .slide: style="font-size: 30px;" -->
### Out-of-process component tests

----
<!-- .slide: style="font-size: 30px;" -->
### Defining acceptance tests for order service
User stories (use case) -> Test cases
```text
Place order
```
```text
As a consumer of the Order Service,
I should be able to place an order
```
```text
(setup)
Given a valid consumer
Given using a valid credit card
Given the restaurant is accepting orders
(execute)
When I place an order for Chicken Vindaloo at Ajanta
(verification)
Then the order should be APPROVED
And an OrderAuthorized event should be published
```
----
<!-- .slide: style="font-size: 30px;" -->
### Write acceptance tests for order service
Gherkin: writing specifications (human readable)
Cucumber: execute the specifications and validate

----
<!-- .slide: style="font-size: 30px;" -->
### Write acceptance tests for order service - setup

----
<!-- .slide: style="font-size: 30px;" -->
### Write acceptance tests for order service - execute

----
<!-- .slide: style="font-size: 30px;" -->
### Write acceptance tests for order service - verification

---
<!-- .slide: style="font-size: 30px;" -->
## End-to-end tests

- 目標:Acceptance test for entire application
- 方法:Launch all services and test together
- 面向:Business-facing tests for entire application
----
<!-- .slide: style="font-size: 30px;" -->
### Designing End-to-end tests
- Write user journey tests (combo of use case)
e.g.: write a single test for create order + revise order + cancel order
- Use Gherkin & Cucumber

Note:
slow, brittle, and expensive way
---
<!-- .slide: style="font-size: 30px;" -->
### Testing Tools - [Pact](https://docs.pact.io)
A code-first consumer-driven contract testing tool
> Pact generates language-neutral acceptance contracts, in the form of JSON pact files.
> These pact files can be created, or tested, by anything that implements the Pact specification, whether the code is Ruby, Javascript, the JVM, or any other language
Note:
Spring Cloud Contract => for java spring
----
<!-- .slide: style="font-size: 30px;" -->
### Testing Tools - [Cucumber](https://cucumber.io/docs/guides/overview/)
A tool that supports Behaviour-Driven Development(BDD)
> Cucumber reads executable specifications written in plain text and validates that the software does what those specifications say.
Note:
Behavior-driven development 行為驅動開發
---
### Q&A

{"metaMigratedAt":"2023-06-17T16:12:47.086Z","metaMigratedFrom":"Content","title":"Testing microservices: Part 2","breaks":true,"contributors":"[{\"id\":\"877c0604-9ea2-40ff-8834-5ea8a760ce56\",\"add\":10802,\"del\":2539}]"}