Java Static Method vs. a Singleton in Validator - java

Why is it considered such an anti-pattern in all cases to use static methods rather than singletons?
I originally wrote the following code
class MyValidator {
public static boolean isValid(String mystring){
if (some conditions ...) {
return true
} else {
return false
}
}
}
I can't really see a reason to make this into an object. It seems just fine as a static method - more testable, eliminating state, etc.
However, I ran into an issue upstream when I wanted to write a controller unit test and mock out the isValid() call. I realize I can use libraries like PowerMock, but people seem to religiously think doing this is an antipattern.
Why is that and what's so wrong with keeping this static?

an anti-pattern in all cases to use static methods rather than
singletons
This is not true. In some cases static methods are absolutely fine, in others not.
Here are some examples from widely used libraries when it is perfectly fine to use static methods:
CollectionUtils in Apache Common Collections
StringUtils in Apache Commons Lang
FileUtils in Apache Commons IO
ClassUtils in Spring Framework
PropertiesHelper in Hibernate
There are no strict criteria in what case static method can be used or should not be used. For some developers this is a matter of their personal preferences, to use static methods as much as possible, or vice versa, to avoid static methods as much as possible.
If you have no strong preferences, you may consider following criteria to decide.
How likely it is that that the functionality provided by the needs to extended or modified in the future? If you see that it is very likely that some methods may need to overridden for some context, then it makes sense to use non-static objects. If it is unlikely (e.g. it is unlikely that the method that compares two strings safely, without throwing NPE), then it is fine to put such functionality in a static method.
How likely it is that there will be more than one class with similar functionality? Is it likely that you may need some generic functionality that uses different implementations in different contexts (e.g. polymorphism may be needed)? For instance, serializing an object to JSON might be a static method. But if you expect that very likely serialization to YML, XML, CSV, PDF or some other formats will be needed, it makes sense to put make such functionality non-static.
How easy would it be to test such functionality? In some cases testing can be easy, e.g. testing a methods that compares two strings without throwing NPE. In other cases it may be pretty complicated, e.g. if such method is called from another code that is being tested.
To your case with MyValidator: I would suppose that later on you may need more than one validator and some generic logic that iterates over list of attributes, determines validators for each attribute and applies them. With static methods it will be very hard to implement it. Where as with non-static methods it may be much easier. For instance, it would be easier to define a generic structure of such classes as following:
public interface Validator<T> {
boolean isValid(T target);
}
Then applying such may be very compact:
for (...) {
validator = findValidatorForObject(obj);
// No need to check the type: String, Integer, ...
if (!validator.isValid(obj)) {
...
}
}

I believe you're setting up a false dichotomy in static methods vs. singletons. Singletons often create problems because they hold state that is hidden from the clients of the classes that access the singletons. But as an alternative to static methods they would not hold state.
Another alternative is for you to define an interface that can be filled with your static method in production code and a mock in testing code:
interface Validator {
boolean isValid(String string);
}
class ClassThatUsesValidator {
private final Validator validator;
public ClassThatUsesValidator(Validator validator) {
this.validator = validator;
}
public void methodToTest(String value) {
if (validator.isValid(value))
...
}
}
// production code
ClassThatUsesValidator obj = new ClassThatUsesValidator(MyValidator::isValid);
// test code
Validator mock = mock(Validator.class);
when(mock.isValid("foo")).thenReturn(false);
ClassThatUsesValidator testObj = new ClassThatUsesValidator(mock);
testObj.methodToTest("foo");
assertThat ...
This way you are avoiding a singleton, using a static method and are still able to mock it for testing.

Related

Non static methods vs Utilty with static methods

I am creating an application in Java which performs data movement task (like copy, move, etc.)
At the higher level, I can provide these operations on object level.
Sample code:
public class DataSource {
public boolean copy(DataSource dsDestination);
public boolean copy(DataSource dsDestination, Filter filter);
public boolean move(DataSource dsDestination);
public boolean exists();
// some other 10-15 methods
}
Or I can provide a utility with static methods:
public class DataSourceUtil {
public static boolean copy(DataSource dsSource, DataSource dsDestination);
public static boolean copy(DataSource dsSource, DataSource dsDestination, Filter filter);
public static boolean move(DataSource dsSource, DataSource dsDestination);
public static boolean exists(DataSource dsSource);
// some other 10-15 methods
}
Which one is better approach in terms of memory management?
The golden rule is: static is an abnormality within good OO design. You only use it if there are good reasons to do so.
You see, static leads to direct coupling between your classes. And it makes testing harder. Of course, the static methods themselves can be easily tested, but what would happen if you want to test a method that calls those static methods (and you have the need to influence what the static method is doing)? Then you might be tempted to turn to Powermock in order to mock those static calls. Which is not really a great idea.
If you insist on separating functionality, you better use interfaces, like:
public class DataSource {
... ctor, equals, ... methods
}
public interface DataSourceCopyAbility {
public void copy(DataSource source, DataSource destintion);
plus corresponding impl class.
EDIT: of course, convenience can be a valid reason to use static methods; for example I am using Objects.requireNonNull() all the time in code. But: those are standard API calls. When I am using them in my code, I really dont mind them to be running. I know that will never ever want to "mock" around such kind of static method invocations!
Finally: I assume you want to return true when your operations passed. Bad idea: booleans should only be used to distinguish between true and false. They are not return codes!
If such a complex operation as copying a DataSource fails - then throw an exception! Or if you really want to go without exceptions, define your own specific ReturnCode class that gives you insight into failing operations!
Forget about memory management.
No matter which method you use, you are still going to create two DataSource objects to call copy or move. There is little difference in memory usage.
What you should focus on instead, is readability and aesthetics :).
Compare these two:
someData.copy(otherData);
DataSourceUtils.copy(someData, otherData);
The second one is more verbose. Also, it seems that we need some other stuff (DataSourceUtils) to help with copying data. It would be less code to write and make more sense if we let the data copy itself (first one).
Another point that I want to point out is that you can add a To in the first one to make it a lot more readable:
someData.copyTo(otherData);
You can't do this with the second method.
I agree with #Jon Skeet , as all the operations need source object which is Datasource itself, then they should be instance methods. They are similar to equals in Object class.
From testable point-of-view instance methods are easy to test.
It depends on the functionality that you are writing in these methods..If the functionality is not using any object specific field values then using static methods would be the correct option.
i.e. make sure the variable information that you are using is not specific to object and data is common to class level
Memory management point of view, by the way, they are equivalent. The functions are share their compiled codes which is stored into the read only memory area. Only the difference between those two are the this pointer context. So it should not occupy any more space if you choose static or non static. Most of the compiled languages are following same manner.
the difference:
dataSource.copy();
copy is not my responsibility and it is a responsibility of DataSource.
DataSourceUtil.copy();
copy is my responsibility,but source code has been written in a utility class to avoid duplication.
Drawing from the experience of Apache Commons Lang library and java.lang.Objects, the advantage of static methods is that they can provide protection from NullPointerException
It is quite common to see something like this in Java code:
if (x != null && a.equals(otherX)) ...
or the practice of putting the literal on the left side:
if ("literal".equals(str)) ...
These are all NPE-protection ways. This is one of the reasons for the abovementioned liberary, and the case for static methods:
if (ds.copy(dest) == true) ... // may throw NPE
if (DataSourceUtil.copy(ds, dest) == true) ... // NPE protection

Shall we avoid writing static methods in our java code for better testability?

I was prefer using static methods in my java code, since I think they are "functional""stateless" and has less side-effect. So there may be some helper classes and methods like this:
public class MyHelper {
public static Set<String> array2set(String[] items) { ... }
public static List<String> array2list(String[] items) { ...}
public static String getContentOfUrl(String url) {
// visit the url, and return the content of response
}
}
public class MyApp {
public void doSomething() {
String[] myarray = new String[]{ "aa","bb"};
Set<String> set = MyHelper.array2set(myarray);
String content = MyHelper.getContentOfUrl("http://google.com");
}
}
But my friend says we should avoid defining such static utility methods, since we call them directly in our code, it will be hard to mock them or test them if they have external dependencies. He thinks the code should be:
public class ArrayHelper {
public Set<String> array2set(String[] items) { ... }
public List<String> array2list(String[] items) { ...}
}
public class UrlHelper {
public String getContentOfUrl(String url) {
// visit the url, and return the content of response
}
}
public class MyApp {
private final ArrayHelper arrayHelper;
private final UrlHelper urlHelper;
public MyApp(ArrayHelper arrayHelper, UrlHelper urlHelper) {
this.arrayHelper = arrayHelper;
this.urlHelper = urlHelper;
}
public void doSomething() {
String[] myarray = new String[]{ "aa","bb"};
Set<String> set = arrayHelper.array2set(myarray);
String content = urlHelper.getContentOfUrl("http://google.com");
}
}
In this way, if we want to write unit tests for MyApp, we can just mock the ArrayHelper and UrlHelper and pass them to the constructor of MyApp.
I agree totally about the UrlHelper part of his opinion, since the origin static code make MyApp untestable.
But I have a little confused about the ArrayHelper part, since it doesn't depend on any external resources and the logic will be very simple. Shall we avoid using static methods at this case too?
And when to use static methods? Or just avoid using it as much as possible?
update:
We are using "TDD" in our development, so the testability of a class often is the most important concern for us.
And I just replace the word "functional" with "stateless" in the first sentence since the that's real what I meant.
You'll probably never want to mock a method that converts an array to a list (or set), and this method doesn't need any state and doesn't depend on any environment, so a static method looks fine to me.
Just like the standard Arrays.asList() (which you should probably use).
On the other hand, accessing an external URL is typically the sort of thing that you want to be able to mock easily, because not mocking it would
make the test an integration test
require to have this external URL up every time you run your tests, which you probably can't guarantee
require to have this external URL return exactly what you want it to return in your test (including errors if you want to test the event of an error).
Just beware of one disease very common amongst Java "experts": overengineering.
In your specific example, you either do or don't have a mockability issue. If you had an issue, you wouldn't be asking general questions, therefore I conclude you don't have an issue at the moment.
The general argument is that static methods are simpler and therefore the preferred choice, whenever there is a choice. A would-be instance method must first prove itself of needing to be an instance method.
If this was my project, I would defer any makeovers into instance methods until such a moment where the need for that became clear and present.
Static means you can call the method without instantiating the class. Its good if you want to package your code into a class and you have a function that just does some logic or something basic.
Just don't use a static function to try and edit member variables in the class (obviously).
Personally I think its fine to use the static function, since it is stateless.
Static methods should be used by answering the question "is this method a functionality of a specific instance?".
You shouldn't decide about a static method according to tests, you should do it according to design. Your examples doesn't need an instance because it makes no sense. So static is the better choice. You can always wrap these methods inside specific tester classes to do your tests.
The only situation in which a self-contained functionality is not static is just when you want to provide multiple implementation, so that you are forced to avoid static because you need inheritance.
I often use static methods:
for factory methods (explicitly named constructors)
to provide a functional layer above an object-oriented layer, to compose the objects
and sometimes for general-purpose functions (Apache Commons has many good examples of this)
I never use "singletons" (static objects) and methods that refer to static objects because they are a complete headache to test and reuse. I also avoid hardcoding anything into a static method that could feasibly need to be changed. Sometimes I will provide multiple methods - one with all the dependencies as parameters and others, with fewer parameters, that call the more flexible method with some default (hardcoded) values.
java.lang.Math is static which is a good example. I thought statics are not beeing garbage collected and should be avoided if possible.
No.
As mentioned by Peter Lawrey in the comment for the question, Java is all about object oriented programming. While certain functional aspects are doable and being put into eg. Java 8, at its core Java is not functional. static breaks so much of the benefits of learning how to do modern Java - not to mention all kinds of not-fun-at-all scoping problems - that there's no purpose to use them unless you're some kind of a Java wizard who really knows what happens when you use that magical keyword.
You are not a wizard. Java is not functional. If you want to be a wizard, you can learn. If you want to program in functional fashion, look into hybrid languages such as Scala or Groovy or alternatively explore the fully functional world, eg. Clojure.

Are static methods a DI anti-pattern?

I am a Java developer who is beginning to grasp the full power of dependency injections, and it suddenly dawned on me that there's no way to inject a static method. So it got me thinking: are static methods DI anti-patterns?
More importantly: if I were to embrace dependency injection, does this mean I need to stop coding static methods? I ask because there is no way to mock them and inject mock statics during unit tests, which is a huge turn-off for me.
Edit: I know that a common way to "wrap" and inject an existing static method is like this:
public class Foo {
public static void bar() { ... }
}
public interface FooWrapper {
public void bar();
}
public class FooWrapperImpl implements FooWrapper {
public void bar() {
return Foo.bar();
}
}
...but I'm not asking how to inject an existing static method...I'm asking if I should stop writing them altogether, if all my code (from this point forward) is going to embrace the notion of DI.
Also, I see a lot of similarly-related questions to this, but couldn't find an exact match that asked this same question. If you see that it is indeed a dupe of another question, please point it out to me and I will close this question myself (please don't just closevote it!).
Static methods are appropriate for things that don't have associated state. Some factory methods, "purely functional" methods like Math.sin, and the like are all perfectly acceptable static methods. java.lang.Math and java.util.Collections have many fine examples of perfectly acceptable static methods.
Fortunately, these methods have no need for dependency injection, or to interact with such things; they're not unusually difficult to test. They don't have dependencies that would need mocking or anything.
On the other hand, static state, or static methods with associated static state, are utterly evil. That is an anti-pattern.
It frequently helps to define a method as being non-stateful (and therefore a legitimate static method) if, and only if, it always returns equivalent output on equivalent inputs. This makes it clear that e.g. database queries and filesystem I/O makes methods stateful, because their outputs will vary depending on what's in the filesystem or the database.
Non-trivial static methods are not compatible with dependency injection. Simply make them instance methods of singletons.
I'll rephrase your question as "How do I distinguish between when a java method should be static and when it shouldn't, when I am using dependency injection?"
In my opinion distinction should not be done purely based on whether is stateful or not, but rather whether you might want to mock the method in a test or not.
I am aware that newer BDD testing framworks like Mockito are fully capable of mocking static methods, but doing so comes at significant performance cost.

PowerMock + Mockito VS Mockito alone

Can anyone please summarize, what exactly features gives you adding PowerMock on top of the Mockito?
So far I've found these:
mock static, final and private methods
remove static initializers
allow mocking without dependency injection - this one isn't clear to me. Can you elaborate?
Does it add anything else? Can you please sum up in several lines?
And do I need to sacrifice something when using PowerMock?
I don't know of other benefits offhand, but I want to address 2 of your sub-questions (and this is way too long for a comment):
allow mocking without dependency injection - this one isn't clear to me. Can you elaborate?
I think this came from the Motivation wiki page where they describe a way of refactoring code to not invoke static methods to make it testable. For a concrete example of what I think they're getting at, let's say you have this code and you want to test the method mocking the behaviour of the static method, without using powermock:
public class MyClass {
public void doGetString() {
...
OtherClass.getString(); //It's complex and scary and needs mocking!
...
}
}
One solution, would be to pull the static invocation into its own object, then inject an object that can be mocked come test time. For example, without using other frameworks, this could look like:
public class MyClass {
public static class StringGetter {
public getString() {
return OtherClass.getString();
}
}
private final StringGetter getter;
//Existing Constructor
public MyClass() {
this(new StringGetter());
}
//DI Constructor
MyClass(StringGetter getter) {
this.getter = getter;
}
public void doGetString() {
...
getter.getString();
...
}
}
I've seperated the behaviour of my method from the behaviour of the static invocation, and can use the DI constructor to inject mocks easily at test time. Of course with powermock I could just mock the static method in place, and run with it.
And do I need to sacrifice something when using PowerMock?
Physically no, but I'd say philosophically yes :). The below are my opinions, and I try to give good reasons behind them, but of course they are opinions so take them with a grain of salt:
The potentially scary thing that is happening with PowerMock is that in order to accomplish the feats of mocking private and static methods, they are using a custom class loader (which shouldn't be present at runtime in production) and changing the bytecode of your classes. Arguably, this should not matter with the vast majority of classes most of the time, but if you think about it, if the bytecode has changed, and certain side effects are no longer present, you're effectively testing different Classes albiet based upon your existing Classes. Yes this is a very academic argument.
You can somewhat mitigate this first argument by having good comprehensive integration and higher level tests that don't use PowerMock. In this way you can be more confident in the behaviours of your objects even if your unit tests are using PowerMock.
The other argument I have against PowerMock, is that it could almost too easily become a crutch. I agree that PowerMock can help with testing code that uses legacy code and other code that you do not have control over. However I would argue that when you have control over the classes that you need to mock, you should avoid its use. If you write a class with a private method or static method that you need to explicitly mock in order to test other methods, my gut instinct would say that this method may be doing too much and should be refactored and broken up. Having PowerMock already available in a project, you may be tempted to just mock it and move on, which would mitigate the pain that should encourage you to refactor the same. Yes there are sometimes due to various technical and non-technical constraints this is not possible, but it's good to solve pain points instead of avoid them :)
PowerMock is an extension to Mockito that allows mocking of static methods, constructors, final classes and methods, private methods, removal of static initializers and more.
Another feature of the Powermock mockito extension is that it supports mocking and stubbing of equals and hashcode.
As with all powermock features to be used with care, but adding (value-based) equality for specific results can be helpful.
One more feature of PowerMock is that we can mock construction of new objects in a method. It is helpful when we cannot change the code of the method to be tested.
For mocking final class we can use org.mockito.plugins.MockMaker. What you would need to do is
Create a folder in your test/resource folder with namemockito-extensions.
Create a file under it with the name org.mockito.plugins.MockMaker.
In that file have just one line mock-maker-inline
This will not require you to do add any new library and hence save some runtime.

Why doesn't Mockito mock static methods?

I read a few threads here about static methods, and I think I understand the problems misuse/excessive use of static methods can cause. But I didn't really get to the bottom of why it is hard to mock static methods.
I know other mocking frameworks, like PowerMock, can do that but why can't Mockito?
I read this article, but the author seems to be religiously against the word static, maybe it's my poor understanding.
An easy explanation/link would be great.
I think the reason may be that mock object libraries typically create mocks by dynamically creating classes at runtime (using cglib). This means they either implement an interface at runtime (that's what EasyMock does if I'm not mistaken), or they inherit from the class to mock (that's what Mockito does if I'm not mistaken). Both approaches do not work for static members, since you can't override them using inheritance.
The only way to mock statics is to modify a class' byte code at runtime, which I suppose is a little more involved than inheritance.
That's my guess at it, for what it's worth...
If you need to mock a static method, it is a strong indicator for a bad design. Usually, you mock the dependency of your class-under-test. If your class-under-test refers to a static method - like java.util.Math#sin for example - it means the class-under-test needs exactly this implementation (of accuracy vs. speed for example). If you want to abstract from a concrete sinus implementation you probably need an Interface (you see where this is going to)?
Mockito [3.4.0] can mock static methods!
Replace mockito-core dependency with mockito-inline:3.4.0.
Class with static method:
class Buddy {
static String name() {
return "John";
}
}
Use new method Mockito.mockStatic():
#Test
void lookMomICanMockStaticMethods() {
assertThat(Buddy.name()).isEqualTo("John");
try (MockedStatic<Buddy> theMock = Mockito.mockStatic(Buddy.class)) {
theMock.when(Buddy::name).thenReturn("Rafael");
assertThat(Buddy.name()).isEqualTo("Rafael");
}
assertThat(Buddy.name()).isEqualTo("John");
}
Mockito replaces the static method within the try block only.
As an addition to the Gerold Broser's answer, here an example of mocking a static method with arguments:
class Buddy {
static String addHello(String name) {
return "Hello " + name;
}
}
...
#Test
void testMockStaticMethods() {
assertThat(Buddy.addHello("John")).isEqualTo("Hello John");
try (MockedStatic<Buddy> theMock = Mockito.mockStatic(Buddy.class)) {
theMock.when(() -> Buddy.addHello("John")).thenReturn("Guten Tag John");
assertThat(Buddy.addHello("John")).isEqualTo("Guten Tag John");
}
assertThat(Buddy.addHello("John")).isEqualTo("Hello John");
}
Mockito returns objects but static means "class level,not object level"So mockito will give null pointer exception for static.
I seriously do think that it is code smell if you need to mock static methods, too.
Static methods to access common functionality? -> Use a singleton instance and inject that
Third party code? -> Wrap it into your own interface/delegate (and if necessary make it a singleton, too)
The only time this seems overkill to me, is libs like Guava, but you shouldn't need to mock this kind anyway cause it's part of the logic... (stuff like Iterables.transform(..))
That way your own code stays clean, you can mock out all your dependencies in a clean way, and you have an anti corruption layer against external dependencies.
I've seen PowerMock in practice and all the classes we needed it for were poorly designed. Also the integration of PowerMock at times caused serious problems(e.g. https://code.google.com/p/powermock/issues/detail?id=355)
PS: Same holds for private methods, too. I don't think tests should know about the details of private methods. If a class is so complex that it tempts to mock out private methods, it's probably a sign to split up that class...
In some cases, static methods can be difficult to test, especially if they need to be mocked, which is why most mocking frameworks don't support them. I found this blog post to be very useful in determining how to mock static methods and classes.

Categories