Why is it advised to use an interface whilst carrying out unit tests using the Mockito framework?What exactly is the use of an interface in unit testing?
There are two reasons: one theoretical, and one practical.
Theory
When working with a mock, you are providing a test double of a component that exists (or will exist) elsewhere in your application; when stubbing you are simulating the responses that the real implementation would have, and when verifying you're doing so against the class's external interface. This makes it very important to have a clear definition of what successful implementors of the interface should be doing and how they should be behaving, regardless of the current implementation: you're providing a different implementation.
Though you could document your implementation's contract method-by-method on the concrete class itself, another method of documenting and formalizing the general contract of the component is to extract an interface. Though I'm no proponent of prospective work (see YAGNI), doing so also makes it clearer if you were to partially or entirely replace your current concrete implementation with another implementation—at which point you would have three implementations of the interface including the mock, and might want to write a test purely against the interface and pass each implementation in separately for verification/validation between them.
Practice
Internally, Mockito dynamically creates your test double by generating a subclass of the class you're trying to test. This means that your mock can only override behavior that a normal subclass can override, and that can make Mockito ill-suited for private classes, encapsulated nested or inner classes, and final classes. In addition, for similar reasons, you will find yourself unable to mock static methods, final methods, and some private or protected methods (particularly wherever which the compiler generates synthetic methods). Because of Mockito's syntax and dynamic nature, Java can't warn about or enforce these rules at compile time, and Mockito can't always detect violations at runtime.
However, when mocking interfaces rather than concrete implementations, Mockito can avoid much of this trouble. Interfaces have no internal method visibility restrictions or final methods, and the types themselves are necessarily public and non-final. So, from a practical standpoint, there are advantages in simplicity and ease of work that come with interfaces but not concrete classes.
Related
I could find many questions/answers on why a method should not make it public. but I could not find anything specific to "default" in Java.
'default', i.e., the absence of a modifier, means package private in Java. Only classes in the same package can access it. Sometimes it is desirable to test an internal method meant for private use of that class in a unit test separate from the rest of that class in order to cover all code paths with clear, concise, and simple tests. When you do this (and the result is cleaner test code that can be maintained with more ease) it is fine to mark that method as package private.
This is not an uncommon strategy. Because the only classes who can use this method must reside in the same package, you still have plenty of control over its use.
Personally I would recommend only doing this for static utility methods that do not depend on the state of their parent class. It is also a very useful technique for testing static methods in abstract classes.
Note that in some cases the need to test private methods may point to the need to break out that part of the class into a separate class instead. This discussion shows some of the common standpoints varying from strict OOP adherence to pragmatism. You often have the possibility to break out that method and make it into a proper public static utility, but that doesn't always make sense, and it doesn't necessarily lead to easier maintained code.
UnitTests are not about testing code, they are about testing public observable behavior, that is: return values and communication with dependencies.
Public observable does not necessarily imply public methods but usually is. We simply test the Methods that other code would call when using the current unit as dependency.
Non public methods (that are not meant to be called by other code) are implementation detail that contributes to the units behavior. Therefore they are testes implicitly.
Keep in mind, that a unit is not connected to a class or a method.
It might even be a group of classes behind a single class acting as "entry point".
A unit is all the code that may change for the same (non technical) reason, a change in the business requirements.
The point here is that implementation details may change while the desired behavior (and thus the UnitTest) does not change. We do such changes to improve the code design (resolve code duplication, apply design patterns and alike). We call them refactoring (This is the third phase in the Test Driven Developement micro cycle). Such a refactoring is exactly the time when we need UnitTest most since when we not change them then they guarantee that the desired behavior of the tested code still exist.
I have some problems with unit testing the following method.
public List<GetSupplyChainResponse> getSupplyChains(){
List<GetSupplyChainsResponse> response = new ArrayList<>();
supplyChainRepository.findSupplyChainsWithCompound().forEach(result
-> response.add(getGetSupplyChainSimpleResponse(result)));
return response;
}
getGetSupplyChainSimpleResponse() is a private method of the same class as getSupplyChains()
Is there any possibility to define return values therefore or do you have any other ideas how I could test the method getSupplyChains()?
You might be overthinking this. The fact that the method that you want to test (getSupplyChains) uses a lambda that calls a private method is irrelevant: they are just implementation details.
What you unit test is the part of your class that you as a client interact with, i.e. its interface. You typically call a public method with some arguments (in this case there are none), you get some return value and that is what you verify in your unit test. If your public method makes use of some private method, it will be tested also.
The problem here is that the response that you get from getSupplyChains obviously depends on what supplyChainRepository.findSupplyChainsWithCompound() returns. What you do in this case is mock that dependency (supplyChainRepository) out: you create a mock instance of SupplyChainRepository, you tell it how to behave, and you pass it to this class, for example via the constructor.
You can either write the mock yourself, or you can rely on a mocking framework to do the heavy lifting like Mockito.
I definitely recommend against unit testing private methods (it leads to brittle tests), or increasing the visibility of those methods (a.k.a. sacrificing your design for the sake of testing).
It is a commonly discussed problem, some prefer using reflection as Janos Binder recommended (How to call a private method from outside a java class), some can live with the fact the the visibility of the methods which we need to mock is increased for the sake of testability.
The problem is quite well discussed here: How do I test a class that has private methods, fields or inner classes?. You can see from the answers and wide discussions that the topic is quite complicated and developers split into factions and use different solutions.
I'd recommend you to remove the private access modifier and to make the method package private (use the default visibility). The common custom is to have the test classes in the same package (but not in the same folder!) as the tested classes.
This will allow you to:
Test the getGetSupplyChainSimpleResponse() method itself, which you should do in any case somehow.
Mock its behaviour for the purpose of testing getSupplyChains(). This you will achieve e.g. by using Mockito framework and its #Spy functionality.
For those who argue that this is "sacrificing your design for the sake of testing", I would answer that if you have private methods which need to be mocked and/or tested, then the design is not ideal anyway so changing the visibility to package private does not mean too big deterioration. The clear solution (from the object oriented design's point of view) is to delegate the behavior of such private methods to separate classes. However, sometimes in the real life it is just overkill.
Does Java have plan that default method substitute for Abstract Class?
I could not find a real case to use default method instead of Abstract?
There are no such plans, which you can derive from comparing the already documented intentions, which differ from the implications of such a plan:
Stuart Marks writes:
The main goal is to allow interface evolution, that is, the addition of new methods. If a new method is added to an interface, existing classes that implement the interface would be missing an implementation, which would be incompatible. To be compatible, an implementation has to come from somewhere, so it is provided by default methods.
…
The main intent of a Java interface is to specify a contract that any class can implement without having to alter its position in the class hierarchy. It's true that, prior to Java 8, interfaces were purely abstract. However, this is not an essential property of interfaces. Even when default methods are included, an interface at its heart still specifies a contract upon the implementing class. The implementing class can override default methods, so the class is still in complete control of its implementation. (Note also that default methods cannot be final.)
and Brian Goetz writes:
The proximate reason for adding default methods to interfaces was to support interface evolution, …
Here are some use cases that are well within the design goals:
Interface evolution. Here, we are adding a new method to an existing interface, which has a sensible default implementation in terms of existing methods on that interface. An example would be adding the forEach method to Collection, where the default implementation is written in terms of the iterator() method.
"Optional" methods. Here, the designer of an interface is saying "Implementors need not implement this method if they are willing to live with the limitations in functionality that entails". For example, Iterator.remove was given a default which throws UnsupportedOperationException; since the vast majority of implementations of Iterator have this behavior anyway, the default makes this method essentially optional. (If the behavior from AbstractCollection were expressed as defaults on Collection, we might do the same for the mutative methods.)
Convenience methods. These are methods that are strictly for convenience, again generally implemented in terms of non-default methods on the class. The logger() method in your first example is a reasonable illustration of this.
Combinators. These are compositional methods that instantiate new instances of the interface based on the current instance. For example, the methods Predicate.and() or Comparator.thenComparing() are examples of combinators.
Note that these do not target the primary domain of abstract classes, like providing a skeleton implementation. Besides the technical differences, abstract classes are semantically different as they bear design decisions about how to implement the functionality, which interfaces, even with default methods, should not. E.g. a well-known example is the List interface, for which two fundamentally different abstract classes exist, AbstractList and AbstractSequentialList and the choice of subclasses either or implementing List entirely different should not be foreclosed by the interface. So the List interface defines the contract and can never be a substitute for an abstract class, which provides a particular base implementation.
Other answers, and links to additional materials, have already adequately covered the technical differences between interfaces and abstract classes. What hasn't been covered well is why to use one over the other.
Consider two different ways to use a class or interface in Java: as a caller or as a subclasser. A caller has an object reference and can call public methods and access public fields via that reference. A subclasser can also access, call, and override protected members of the superclass. Classes can have protected members, but interfaces cannot.
A common question seems to be, now that we have default methods, why do we need abstract classes? A default method is part of what the interface presents to callers. A protected method on a class is not available to callers; it is only available to subclassers. Thus, if you want to share implementation with subclassers, then use a class (or abstract class) and define protected members and fields.
The protected mechanism allows a class to communicate with subclassers, distinct from the way it communicates with callers.
But the OP asks the opposite question: why would one use default methods in preference to abstract classes? In the situation where you actually have a choice (i.e., your abstraction doesn't require state, or protected methods, or any of the things that abstract classes have that interfaces do not), interfaces with default methods are far less constraining than abstract classes. You can only inherit from one class; you can inherit from many interfaces. So interfaces with default methods can behave like stateless traits or mixins, allowing you to inherit behavior from multiple interfaces.
Given that interfaces and abstract classes are used for different purposes, there is no plan to remove or replace anything.
Default methods can't substitute abstract classes, as abstract classes can (and often do) have fields. Interfaces can only contain behaviour and not state, which is unlikely to change in the future as multiple inheritance of state in Java is seen (rightly or wrongly) as evil.
They can also have final methods, which is another thing you can't mimic with default methods.
If anything, interfaces with default methods resemble traits rather than abstract classes, but the match isn't perfect. Using interfaces as traits is something that has to be done very carefully and knowing the limitations they come with. (Such as any implementing class can override a default method, potentially ruining the trait.)
More on this here.
One of the reasons why default methods in interfaces were introduced was to allow adding new methods to the JDK interfaces.
Without this feature once a class has been compiled with a specific version of an interface no new methods can be added to this interface. With the default methods in interfaces feature interfaces can be changed.
I have an interface whose implementors all require a common method internally - it is not required to be part of the public interface. Also, there are future interfaces in the pipeline that will need this functionality.
Is it good design to have this interface implement a different interface that just has this default method implemented? This way all implementors have access to the common method seamlessly. But, since there is no concept of 'private default' methods, the method is also exposed to clients, which I feel isn't right.
Is resorting to a separate concrete utils class a better means to this end? Or creating an abstract implementation of my interface with the required method and have clients extend that?
EDIT: My question is more inclined towards finding out whether an interface with only default methods is sound, design-wise? Having static methods in the interface does not seem to be in contention actually.
interface is used to segregate the users and the implementors. In your situation, i think an abstract class is more suitable.
default methods are overridable methods, but your scenario describes a utility method that is intended to be neither, part of the API nor overridable. Note that since default methods can work on the instance only in terms of the public methods defined in the interface, i.e. can not access any internals, there is no difference between:
interface MyInterface {
default ReturnType method(Parameter parameter) {
}
}
and
interface MyInterface {
static ReturnType method(MyInterface instance, Parameter parameter) {
}
}
regarding what the method can do. It’s only that within the default method, you may omit the qualifying this. when invoking other interface method, whereas in the static method, using instance. is mandatory. But in either case, you may invoke all public methods of the MyInterface instance but nothing else.
But the static method is not overridable and you may move it to any other class to avoid it becoming part of MyInterface’s API. But note that there is little reason to worry about the accessibility of the utility method. Since it can’t access any internals of the implementation classes, it can’t offer anything that the callers couldn’t do otherwise. It only makes it more comfortable than re‑implementing the functionality at the caller’s site. So moving the method into another class primarily documents the intention of not being part of the MyInterface’s API. It’s no harm, if the method is public there (to support implementations in arbitrary packages).
See for example the methods in the class StreamSupport. They are there to aid implementing Streams, needed by different packages, but not part of the Stream interface API itself. The fact that the methods there are public does not create any harm, they don’t offer anything you couldn’t do yourself using the other available public APIs. But it’s convenient for implementors not needing to do it themselves.
Assume I have classes ClassX in production code (src/main/java) and ClassXTest in test code (src/test/java). In some test methods I want to tamper what one of the methods of ClassX returns, so I override ClassX and its method. I do not want to use any mocking frameworks or this class to be anonymous. Is there any naming how such classes should be named?
Personally, I would call these classes: ClassXTestImpl
It's not the greatest naming convention in the world, but it makes it obvious that it is test code and is not expected to be used by the production code. You could also make it a private inner class of the test class in which it is being used, then it wouldn't even be accessible by you production code.
Generally, I don't like calling things Impl, but in this case, the ClassX part will define what the class actually does and the TestImpl bit is just to mark it as a test implementation.
An aside about partial mocking:
I know you said that you didn't want to use mocking frameworks, but if you're replacing method1 in order to make method2 easier to test and both methods reside in the same class, then what you're doing is a form of partial mocking, whether you do it with a framework or not. It's difficult to find documentation for Partial Mocking that isn't linked to a particular framework, so I'll provide EasyMock's documentation but point out that most mocking frameworks support this kind of mocking.
These classes are called "test-specific subclasses" and there doesn't seem to by any naming convention. http://xunitpatterns.com/Test-Specific%20Subclass.html gives some examples of overriding classes that are under tests.