Trying ArchUnit with Typescript
I recently learned about something called ArchUnit. It seems that it can test dependencies. I want to try it out right away, so I'll leave this as a memo.
ArchUnit
ArchUnit is a free, simple and extensible library for checking the architecture of your Java code using any plain Java unit test framework. That is, ArchUnit can check dependencies between packages and classes, layers and slices, check for cyclic dependencies and more. It does so by analyzing given Java bytecode, importing all classes into a Java code structure.
It's a library that can test Java architecture, and it seems to be able to test dependencies between packages, classes, layers, and slices(?). So, I want to test this diagram that I've seen more than my parents' faces.
I want to do ArchUnit with Typescript
ArchUnit is made in Java. I want to do ArchUnit with Typescript. So, I found a good library.
https://github.com/MaibornWolff/ts-arch
I don't have any particular preference, I think anything that can test the architecture is fine. In extreme cases, I think you could make your own by parsing the source code into AST and extracting dependencies.
I tried it
The source code I tried is placed below. Please refer to it.
https://github.com/silverbirder/try-archunit
The overall source code tree is as follows.
src
└ 1_enterprise_business_rules
└ entities
└ Entity.ts
└ 2_application_business_rules
└ use_cases
└ UseCase.ts
└ 3_interface_adapters
└ controllers
└ Controller.ts
└ gateways
└ Gateway.ts
└ presenters
└ Presenter.ts
└ 4_frameworks_and_drivers
└ web
└ Web.ts
└ clean_architecture.puml
└ clean_architecture.test.ts
Each product code is just importing files from the lower hierarchy.
// src/4_frameworks_and_drivers/web/Web.ts
import "../../3_interface_adapters/gateways/Gateway";
import "../../3_interface_adapters/controllers/Controller";
import "../../3_interface_adapters/presenters/Presenter";
// src/3_interface_adapters/controllers/Controller.ts
import "../../2_application_business_rules/use_cases/UseCase";
// src/2_application_business_rules/use_cases/UseCase.ts
import "../../1_enterprise_business_rules/entities/Entity";
// src/1_enterprise_business_rules/entities/Entity.ts
The dependency is represented in the component diagram in the following file.
# clean_architecture.puml
@startuml
component [4_frameworks_and_drivers] #Blue
component [3_interface_adapters] #Green
component [2_application_business_rules] #Red
component [1_enterprise_business_rules] #Yellow
4_frameworks_and_drivers --> 3_interface_adapters
3_interface_adapters --> 2_application_business_rules
2_application_business_rules --> 1_enterprise_business_rules
@enduml
When visualizing the UML, it looks like the following diagram.
The test code is as follows.
// clean_architecture.test.ts
describe("architecture", () => {
it("Check dependency", async () => {
const architectureUml = path.resolve(__dirname, "clean_architecture.puml");
const violations = await slicesOfProject()
.definedBy("src/(**)/")
.should()
.adhereToDiagramInFile(architectureUml)
.check();
await expect(violations).toEqual([]);
});
});
This test case will PASS.
Now, let's write some violation code.
// src/3_interface_adapters/controllers/Controller.ts
import "../../2_application_business_rules/use_cases/UseCase";
import "../../4_frameworks_and_drivers/web/Web";
The 3rd layer is using the higher 4th layer. If you run the test in this state,
It has beautifully Failed. In other words, you can automatically detect errors in dependencies.
Finally
The larger the project, the more complex the dependencies tend to be. Even if you have properly designed the dependencies of (what would be in Java) packages and classes, someone might break them. It's a shame to have your carefully crafted design broken, so let's protect it with test code!
Share
Related tags
- Trying Out container-structure-test on a Docker Image
- Integration Testing for Next.js and DB using Testcontainers
- Trying Million Lint
- Trying the Playwright Component Test
- I want to do Document Testing with Typescript
- How to Mock tRPC Communication on Storybook with MSW
- E2E Testing with Cucumber and Screenplay Design
- Comprehensive Testing Pattern Guide for Web Frontend
- Mockable unit testing methodology completed only with BigQuery
- Investigated and Summarized Testing Perspectives for Web Apps (25 Selections)
- I want to test with Google Apps Script too! (Clasp + Typescript + Jest)
- Things to Keep in Mind When Writing Unit Tests
- Continuously Monitor Visual Regression Tests with CircleCI + BackstopJS (Puppeteer)