🏁
Best Practices
  • Introduction
  • The Big Picture
    • Principles
      • Software engineers solve business problems
      • Programming is a social activity
      • Attention is the most precious resource in a project
      • Simplicity is the best ally in the long run
      • The only problem to solve is the one we have today
    • Architecture
      • Domain
      • Services
      • Persistence
      • HTTP
      • UI
    • Naming
  • Constraints
    • TypeScript
    • Monorepo
    • Monolith
    • Versioning
  • Source code
    • Declarative programming
    • The README
    • Modules
    • Folder structure
    • Code formatting
    • Code comments
  • The Outside World
    • Runtime configuration
    • Logging
  • Testing
    • The purpose of testing
      • End-to-end tests
      • Integration tests
      • Unit tests
  • Tools
    • Git
  • Resources
    • Resources
Powered by GitBook
On this page

Was this helpful?

  1. Testing
  2. The purpose of testing

Integration tests

PreviousEnd-to-end testsNextUnit tests

Last updated 5 years ago

Was this helpful?

Integration tests have the same aim as e2e tests: to verify the are working by executing an API (REST, GraphQL, etc.).

Aim to test on real infrastructure: tools like Docker (Docker Compose) can spin up anything quickly. Mocking 3rd party services might be OK if there is no way around it, but try to avoid mocking your services.

Integration tests spin up the public interface (HTTP/GraphQL) and other resources (databases, etc.), set the configuration just like in regular deployment.

The assertions are all related to the high-level use cases: users can log in, see products, give us their money etc. Thanks to the machine-friendly API, these tests are more robust than e2e tests, so a lot more edge cases can be verified (higher coverage).

Do not auto-generate tests based on a GraphQL schema: the schema might be unfit for business purposes but still be technically valid.

Since we inject all modules that deal with the external world to the services, it's straightforward to use in-memory implementations during testing. The drawback is that someone must write these implementations and keep them up-to-date with the "real" ones - this is potentially a lot of extra effort. All in all, the gain doesn't justify the effort, in my opinion.

Suggestion: put integration tests in the public interface project, next to the src folder:

graph/
  src/
  features/ # <-- here
    chopChips.feature.ts

Persistence tests

I suggest to cover the with dedicated integration tests, to gain confidence in data integrity. The tests should prove that the specific implementation of the handles CRUD commands as expected. The benefit of having a single API is that the same test can run against multiple implementations (just inject the test subject).

use cases
persistence modules
persistence API