55

For a unit test, I need to mock several dependencies. One of the dependencies is a class which implements an interface:

public class DataAccessImpl implements DataAccess {
    ...
}

I need to set up a mock object of this class which returns some specified values when provided with some specified parameters.

Now, what I'm not sure of, is if it's better to mock the interface or the class, i.e.

DataAccess client = mock(DataAccess.class);

vs.

DataAccess client = mock(DataAccessImpl.class);

Does it make any difference in regard to testing? What would be the preferred approach?

Jasper
  • 11,590
  • 6
  • 38
  • 55
helpermethod
  • 59,493
  • 71
  • 188
  • 276
  • 1
    Here are some other thoughts about mocking classes. Nice read, imho: http://stackoverflow.com/questions/1595166/why-is-it-so-bad-to-mock-classes – guerda Feb 10 '12 at 10:56

5 Answers5

64

It may not make much difference in your case but the preferred approach is to mock interface, as normally if you follow TDD (Test Driven Development) then you could write your unit tests even before you write your implementation classes. Thus even if you did not have concrete class DataAccessImpl, you could still write unit tests using your interface DataAccess.

Moreover mocking frameworks have limitations in mocking classes, and some frameworks only mock interfaces by default.

Kuldeep Jain
  • 8,409
  • 8
  • 48
  • 73
  • Hi @Kuldeep Jain, what if the implementation class has a method that calls an external service (which needs to be mocked)? We cannot test it mocking the interface right? We will have to mock the implementation class to mock this method. – Agent47 Mar 01 '21 at 08:20
9

In most cases technically there is no difference and you may mock as class so an interface. Conceptually it is better to use interfaces because of better abstraction.

Alex Nikolaenkov
  • 2,505
  • 20
  • 27
6

You should mock the interface since it will help ensure you are adhering to Liskov Substitution Principal (https://stackoverflow.com/a/56904/3571100).

Community
  • 1
  • 1
jordan
  • 959
  • 7
  • 17
  • 1
    It would be interesting to know, how can you achieve this by mocking the interface? i can mock the interface but in the class implementation I can violate the Liskov Substitution. – karlihnos Aug 02 '17 at 15:16
  • @karlihnos the link I provided states "Functions [...] must be able to use objects of derived classes without knowing it." in other words we should program to the interface rather than implementation. So in the class under test we can help to achieve LSP by programming to the interface. Of course doing this does not say anything about whether any mocked interfaces implementations will adhere to LSP or not. – jordan Jan 13 '18 at 17:34
6

It depends. If your code depends on the class and not on the interface you must mock the class to write a valid unit test.

onof
  • 17,167
  • 7
  • 49
  • 85
  • 17
    Or listen to the test and make the code depend on an interface, as it probably should. – blank Feb 10 '12 at 11:26
  • This is just wrong. If you see it different please explain. TDD even requires to test against interfaces and not implemented classes. If your code depends on a class instead of the given interface you have another bigger issue. – Anna Klein May 02 '19 at 18:37
  • @AnnaKlein my answer is not about the target code but the unit test. If your code dependends on an implementation instead of an interface (in the real world it's a common scenario), and you have to write a UT on that you should mock the class, otherwise your unit test probably wouldn't compile or simply wouldn't be complete. – onof May 07 '19 at 14:57
3

If you only use it through interface and it's not a partial mock, there is no difference other than your inner feeling. Mocking the class will also mock non-used public method if the class has them, but that is not a big deal to consider.

Alex Abdugafarov
  • 6,112
  • 7
  • 35
  • 59