Why Mockito’s @InjectMocks is evil

Why Mockito’s @InjectMocks is evil:

TLDR: It fails to inject silently

@InjectMocks will try to satisfy a dependency with a @Mock by adding to the system under test via constructor, setter, or property.

If any of those do not succeed, it will fail silently, and you won’t know why you have a NullPointerException, for example.

Better to explicitly declare and add your mocks with Mockito.mock() instead of relying on @InjectMocks to autowire your dependencies.

Automation Strategy Manifesto

Automation is key to a successful DevOps strategy

In order to accelerate release velocity from quarterly to bi-weekly we need to develop and release software in smaller cycles.

This allows us to make decisions in an agile manner and get faster feedback from users.

But the release cycle has inherent friction.

To reduce this friction and release more frequently, we will need to automate our software build and deployment processes.

By using a DevOps strategy to create create consistent automated delivery processes.

Continuous integration & delivery tools can help with this.

In order to have confidence in our release cycle, we need to be able to test quickly.

To avoid testing becoming a bottleneck, we need to have automated, reliable tests.

Traditional end-to-end functional test automation can be slow, brittle, and expensive to maintain.

So our aim is to provide thorough test coverage with unit tests.

Unit tests are isolated, target a single object, method, or procedure and are faster and more consistent than end-to-end tests.

Unit tests provide a way to mitigate technical debt by making refactoring easier, and giving you confidence to change existing code without introducing regressions.

We will use code coverage tools it identify where we can improve tests, but not as a sole metric of quality.

Since too many unit test add technical debt tool.

Because not everything can be unit tested, we will use integration and system testing to cover areas of the application not easily tested at the unit level.

Also, because integration points (especially with external system) are the most likely place for unexpected errors, we will focus on testing these areas.

Manual acceptance and exploratory testing is also necessary, and accomplishes some things better.

Because of thorough unit, integration, and system test automation, people can focus on those aspects that are more challenging to automate.

100% automation is not the goal, because sometimes that takes more time and effort.

Test automation also incurs technical debt and can make code rigid and resistant to change if you also have to change tests.

In order to have confidence in tests, we will strive to keep results “green” — no failing tests are allowed to live.

To make sure automation is useful and timely, we will create a build-test-deployment pipeline including:

  • source control management
  • mainline development & branching strategy
  • code review process on pull requests
  • static analysis tools for code quality & security
  • automated builds
  • unit testing code while mocking external dependencies
  • code coverage metrics
  • controlled and versioned code artifacts
  • ephemeral & interchangeable environments created on demand
  • automated infrastructure provisioning
  • automated deployment & configuration
  • secure secrets sharing
  • blue green & canary releases
  • post-deployment smoke testing and monitoring & metrics
  • automatic rollback & notification