26

Somebody told me @Mock is usually employed only for unit tests but I think is useful for substituting the external parts outside the tested class. Is it correct to mock in integration tests?

  • 3
    I've VTC'ed as opinion based, but the short answer is yes. – Dawood ibn Kareem Aug 31 '18 at 02:21
  • 1
    If every dependency of a unit under test has been mocked, there is no integration with any external unit, hence the test is not an integration test. On the other hand, if integration is tested one dependency at a time, mocking other dependencies, it could still be fine. – manish Aug 31 '18 at 02:52
  • 1
    Possible duplicate of [Mocking for integration tests](https://stackoverflow.com/questions/10131723/mocking-for-integration-tests) – Ori Marko Aug 31 '18 at 05:15
  • 5
    I don't think that question is opinion based. It is a very relevant and important question and is answerable with yes or no. – mio Sep 01 '18 at 07:42

4 Answers4

45

In the end, this is all about wording.

When you think of "correct" in its very fundamental sense, as in correctness, then the answer is simply: no.

You see, the goal of an integration test is to ensure that your integrated system (consisting of multiple, different components) functions as expected. The purpose of an integration test is to verify that your "plumbing" of components works as expected. Therefore: you can't verify that your system works when parts of that system are mocked out.

But then, you can think "correctness" less strictly.

Example: companies selling cars have to test ECUs. Basically a piece of hardware, running a potentially huge software stack. These ECUs normally operate within cars. So when you want to integration test an ECU, you would have to put the ECU into a car for testing, right? A car that probably doesn't exist yet. The solution here: there are hardware emulators. You plug the ECU into that emulator, and the ECU "thinks" that sits inside a real car.

So: there are good arguments to claim "a true integration test can't use mocking", but at the same time, in the real world, such "mocking" happens all the time.

The real answer is therefore: it depends on context. Therefore there isn't a universal answer. Instead, this is about communication. You "simply" have to ensure that all people in your group/org have the same understanding of such terms.

The term itself can be interpreted in different ways. You (jointly!) pick that definition that best fits your needs, to then make sure all people contributing to your project share that view (or at least know about it).

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Imo mocking and simulating can be two very different things. I'd say that mocking is kind of a subset of simulating. Even if the transition might be gradual and blurry. However, simulating attempts to replicate the environment as close as possible imo, whereas mocking is rather a "lazy" kind of simulating, which is why I see it as subset. Sometimes in software development we'd just `mock(AnyObject.class)` e.g. just to avoid null-pointer exceptions (= bad practice). This means that the object might even be in a state that does not really make sense in the prod-env. But now your tests are green. – Stefan Falk Jul 27 '23 at 08:21
10

Yes, there are scenarios where you can use @Mock (mainly for stubbing) in integration tests. Especially if you want to integration test a part of your class.

For example, if you want to test the communication with an external service A there is nothing wrong with mocking the rest that concerns communication with service B.

Another example, if you test a workflow it makes sense to have an integration test that tests the paths by mocking the single steps/activities.

Personal opinion (controversial and there are many different terminologies): there are many shades of unit and integration tests. In my understanding a unit test is only testing a single class in isolation. But often I write tests that test several classes combined, what is already a kind of integration test in my point of view. Then there are tests that might test a single component by mocking external services, I call them system tests. And then there might be tests that test a single component against external services that are not mocked, I call these tests system integration tests. In all these scenarios it might be feasible to mock/stub certain parts and focus on one aspect in a single test class.

mio
  • 562
  • 5
  • 19
  • 1
    Good answer and indeed the things are not white or black. Not directly the matter but as you refer that, I would like to give my opinion. About writing Integration tests, I think that an important thing is choosing these that have value. Integration test can be done at multiple levels. We have to do the right choices to not explode the number of tests and introduce a some of dup in the test code. – davidxxx Sep 01 '18 at 11:16
  • If you mock the external dependencies to service B, then how do you properly test the interactions between A and B if not in integrated tests ? – renatodamas Jul 24 '22 at 20:37
5

Is it correct to mock in integration tests?

General case : you don't mock in the integration tests

In a general way, mocking and integration tests don't suit together.
Most of time, you want to use the one or you want to use the second, not both.

But sometimes you want to mock in the integration tests because the logic that you want to assert can be correctly tested only in this frame

If you rely on a framework or a library that perform many things for you and that you need to test the logic you specified in this frame, you will finish by writing more integration tests than unit tests as unit tests are often not enough at all to cover the application code.
But full integration tests have no isolation at all with other components (so side effects are possible : a test can so be successful for bad reasons), these are generally slow, so are generally not executed on the local machine which provide late feedback for developers.
So writing only full integration tests is generally not acceptable. For this kind of context the idea to mock during integration tests makes really sense.

Spring Boot and test slice : a good example

An application powered up by Spring Boot falls in this category.
In fact we want to run the container to be able to test some specific parts (persistence, controller and so for) but we don't want to load the whole container and associated components.
So mocking some specific parts make really sense.
And Test slices from Spring Boot allows to mock while the component under test is tested at a some level of integration :

Spring Boot’s auto-configuration system works well for applications but can sometimes be a little too much for tests. It often helps to load only the parts of the configuration that are required to test a “slice” of your application. For example, you might want to test that Spring MVC controllers are mapping URLs correctly, and you do not want to involve database calls in those tests, or you might want to test JPA entities, and you are not interested in the web layer when those tests run

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • 1
    Yes, I agree. Without focusing on certain aspects of an application these tests would fail for issues that are not related to the part that they are testing and they would be very difficult to maintain because of their complexity. In my opinion this example shows very well why it is useful and perfectly acceptable to mock/stub parts of a system in integration tests. – mio Sep 01 '18 at 08:43
  • @mio The points that you quoted encouraged me to reformulate. Thanks – davidxxx Sep 01 '18 at 11:16
  • 1
    @GhostCat That is a thing that may happen :) – davidxxx Sep 04 '18 at 19:47
-3

There are 2 types of testing. Unit testing and Integration Testing. You can use Mocks to perform Unit testing. In Unit testing you test individual methods and focus is on testing the individual methods behaviors. So using mocks make sense Incase of unit testing.

Where as you can not use mocks to perform Integration testing. Integration testing usually involves all the dependent systems integrated and we perform it on any server / cloud.

Naga
  • 800
  • 7
  • 8