0

My company does not allow to use Mockito.verify in Unit Test. There even is a customized sonar rule about it.
The rule is as below.
The results should be verified by assertions rather than using the verify to do process verification. Because if we verify the process, need more effort to maintain tests after the process is changed,but input and output remain the same. Make sure that every line of code has an impact on the results, and assert the results to prove the logic is correct.
Noncompliant Code Example

verify(graphics2D, times(1)).dispose();// Noncompliant

Compliant Solution

assertThat(((SunGraphics2D) graphics2D).getSurfaceData()).isInstanceOf(NullSurfaceData.class);

For database or middleware operations, assert the data was write successful using the embedded database or middleware.

For restful requests, use wiremock's verify to assert that the mock server received the corresponding request。

WireMock.verify(postRequestedFor(urlEqualTo("http://localhost:8080/query"))
                .withHeader("Content-Type", equalTo("application/json"))
                .withRequestBody(equalToJson("{" +
                        "\"testing-library\": \"WireMock\"," +
                        "\"creator\": \"Tom Akehurst\"," +
                        "\"website\": \"wiremock.org\"" +
                        "}")));

My question is, does any other IT company have similar rule to avoid using Mockito.verify in Unit Test? Is it a good rule or evil rule? Thank you very much.

2 Answers2

1

Well, this would require a long answer, but I will try to make it short. Change company. It's basically two different kind o tests. In one case you're checking input and output (assert), in the other case your output very likely is void and then you just verify that the function is called.

Besides that, you use verify for "integration tests" where you want to verify that the functions are called and also you may want to verify the order in which they are called with "inOrder()" as explained here: Mockito verify order / sequence of method calls

Sometimes unit tests and integration tests overlap. There are 2 subtypes of integration tests:

  • those that because of a matter of necessity require mocks;
  • those that do not make use of mocks at all.

Lately a maven plugin has been used which allows to spawn docker containers at will during the test or verify phases.

<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.33.0</version>

That allows you to run integration tests and end to end tests within your project in a common Jenkins pipeline. The only problem appears when you cannot use docker in Jenkins because docker is not installed on the machine that runs the tests.

Davide Pugliese
  • 366
  • 7
  • 16
1

Asserts without verifications can only check an end state after the tested method returned. To have a complete end state, you need to have all real objects, no mocks. Any mock being used means you don't have a full state at the end and you can't check everything you should check without using verify. So, if using verify is forbidden, then you shouldn't use Mockito at all. And you should be aware that you are writing integration tests instead of unit tests.

An integration test however won't tell you what went wrong and where to look for the root cause: is the bug in your code or in the code of a third party library you are using? You will have to investigate and debug yourself to find out. And that is why you need real unit tests.

If the method being tested needs to be unit tested, that means the test should test what that method is doing without depending on the implementation of any method that is being called. When the method being called is in a mock, the data send to the mock normally goes no where and you can't verify that the correct data was passed in the call. You can stub the method with an answer object that stores the parameters and assert them afterwards. but then you are just implementing your own verification method using asserts. When the method being called is not a mock, your test will depend on the implementation of that method and is no longer a unit test. Changing the implementation of the called method can break unit tests of a lot of methods which are calling that method.

Or in short: if your company doesn't want you to use verify, they don't want you to write unit tests, but integration tests.

Both unit tests and integration tests are useful and are complementary to each other. Both are maintainable if structured well. But tests become difficult to maintain when you mix both types (unit tests using real objects instead of mocks or integration tests using mocks). So, for integration tests, avoiding verify (and mocks) is a good rule. For unit tests it is a bad rule because it makes it impossible to write real unit tests.