java / jUnit testing classes with one public method [duplicate] - java

This question already has answers here:
How do I test a class that has private methods, fields or inner classes?
(58 answers)
Closed 8 years ago.
I have a class that has one public method (cheer for single responsibility principle) except within that method there is a try that lists about 20 method calls. In terms of testing and / or refactoring and testing, how would I go about this? I'm new to java. Looking for a better way to structure and test this code. Any suggestions / pointers to best practices would be appreciated! Thanks!

Just because you have one public method doesn't mean you're following the Single Responsibility Principle. For example, you could write an entire project directly in the main method if you wanted to. That main would have many responsibilities.
What I'd do is test it through the public method if you can. If you can't, that suggests there's to many responsibilities in your class. You should discover these separate responsibilities and move them into other classes with their own public methods and then test the new class separately.

I agree with the previous answer. You should really consider having methods that accept parameters and perform a single action and return the result. If you can't break up your code into smaller segments, then you may add assertions directly to your code without use of a separate unit test class. Here is a link to show you how to add directly to your code.
http://www.deitel.com/articles/java_tutorials/20060106/Assertions.html

Look at the specification for the method. (There is a specification, right?)
Every sentence or part-sentence in the specification that describes one thing that the method does should induce one test case - that is, one method in the test class that includes an assertion. If a sentence talks about behaviour in different scenarios (e.g. if the price field is > 0 then add a line to the statement, otherwise throw an IllegalArgumentException), then it might give you multiple test cases.
But seriously, 20 method calls within one method? That sounds to me like rather a fragile design. Please reconsider it.

Related

"should be accessed in a static way" [duplicate]

This question already has answers here:
class or method alias in java
(8 answers)
Closed 3 years ago.
I have a class with a probably unnecessarily cumbersome name, that contains a lot of static methods I use elsewhere.
Rather than fill my code with a lot of
VeryUnnecessarilyLongCumbersomeName.doThingFoo();
VeryUnnecessarilyLongCumbersomeName.doThingBar();
VeryUnnecessarilyLongCumbersomeName.doThingEgg();
VeryUnnecessarilyLongCumbersomeName.doThingSpam();
I would rather have
VeryUnnecessarilyLongCumbersomeName thing = new VeryUnnecessarilyLongCumbersomeName();
thing.doThingFoo();
thing.doThingBar();
thing.doThingEgg();
thing.doThingSpam();
However, this gets the warning
"the static method doThingFoo() should be accessed in a static way."
I know there are multiple solutions here. Use better class names. Make it not static. Ignore it because it's just a warning.
But I don't actually think it should be a warning. What harm does doing it this way cause? Is there a more elegant/correct way to make my code less clunky that isn't one of the above solutions?
NOTE: I suspect this might warrant the coding-style tag and therefore be considered off-topic and get rejected. I was thinking there's room here for a question like this, however, so I leave it up to y'all.
Although it is not technically harmful because it technically works, the problem with this is it is misleading, and any values that the instance thing contains, do not actually matter at all for the results of the methods.
Typical Java Convention:
When accessing a method through an instance, one would expect the result to be dependent on the values of the instance.
When accessing a method through a Class name, one would expect the result to be independent of the values of any instance.
Your way:
You are accessing a method through an instance and expecting it to be independent of any instance.
So why use an instance for an instance independent method? That is why it is misleading. I would suggest attempting to shorten the class name rather than accessing static methods through an instance.
How about changing the VeryUnnecessarilyLongCumbersomeName class?
Static methods are there to be used without instances. They are meant to be used if you want to invoke the method without first initializing a class. The downside of using static methods is that you lose all kinds of OOP benefits; You lose virtual dispatch and subsequently polymorphism. You can never override that method in a derived class. Of course you can declare a new (static) method in a derived class, but any code that accesses it has to be aware of the entire class hierarchy and do explicit checking and casting, which is precisely what OO is supposed to avoid.
Also, it is confusing. When another programmer sees your code, he/she will think upon seeing a static he/she will assume that it will not require a valid instance to invoke the method.
TLDR; don't do it and stick with the best practices =)

Using a function in two unrelated Java classes

I have two classes in my Java project that are not 'related' to each other (one inherits from Thread, and one is a custom object. However, they both need to use the same function, which takes two String arguments and does soem file writing stuff. Where do I best put this function? Code duplication is ugly, but I also wouldn't want to create a whole new class just for this one function.
I have the feeling I am missing a very obvious way to do this here, but I can't think of an easy way.
[a function], which takes two String arguments and does soem file writing stuff
As others have suggested, you can place that function in a separate class, which both your existing classes could then access. Others have suggested calling the class Utility or something similar. I recommend not naming the class in that manner. My objections are twofold.
One would expect that all the code in your program was useful. That is, it had utility, so such a name conveys no information about the class.
It might be argued that Utility is a suitable name because the class is utilized by others. But in that case the name describes how the class is used, not what it does. Classes should be named by what they do, rather than how they are used, because how they are used can change without what they do changing. Consider that Java has a string class, which can be used to hold a name, a description or a text fragment. The class does things with a "string of characters"; it might or might not be used for a name, so string was a good name for it, but name was not.
So I'd suggest a different name for that class. Something that describes the kind of manipulation it does to the file, or describes the format of the file.
Create a Utility class and put all common utility methods in it.
Sounds like an ideal candidate for a FileUtils class that only has static functions. Take a look at SwingUtilities to see what I'm talking about.
You could make the function static in just one of the classes and then reference the static method in the other, assuming there aren't variables being used that require the object to have been instantiated already.
Alternatively, create another class to store all your static methods like that.
To answer the first part of your question - To the best of my knowledge it is impossible to have a function standalone in java; ergo - the function must go into a class.
The second part is more fun - A utility class is a good idea. A better idea may be to expand on what KitsuneYMG wrote; Let your class take responsibility for it's own reading/writing. Then delegate the read/write operation to the utility class. This allows your read/write to be manipulated independently of the rest of the file operations.
Just my 2c (+:

trying to use only one method name

When I was programming a Form Validator in PHP, when creating new methods, I needed to increase the number of arguments in old methods.
When I was learning Java, when I read that extends is to not touch previously tested, working code, I thought I shouldn't have increased the number of arguments in the old methods, but overridden the old methods with the new methods.
Imagine if you are to verify if a field is empty in one part of the form, in an other and in yet an other.
If the arguments are different, you'll overload isEmpty, but, if the arguments are equal, is it right to use isEmpty, isEmpty2, isEmpty3, three classes and one isEmpty per class or, if both are wrong, what should I have done?
So the question is:
If I need different behaviors for a method isEmpty which receives the same number arguments, what should I do?
Use different names? ( isEmpty, isEmpty2, isEmpty3 )
Have three classes with a single isEmpty method?
Other?
If that's the question then I think you should use:
When they belong to the same logical unit ( they are of the same sort of validation ) but don't use numbers as version, better is to name them after what they do: isEmptyUser, isEmptyAddress, isEmptyWhatever
When the validator object could be computed in one place and passed around during the program lifecycle. Let's say: Validator v = Validator.getInstance( ... ); and then use it as : validator.isEmpty() and let polymorphism to it's job.
Alternatively you could pack the arguments in one class and pass it to the isEmpty method, although you'll end up with pretty much the same problem of the name. Still it's easier to refactor from there and have the new class doing the validation for you.
isEmpty( new Arguments(a,b,c ) ); => arguments.isEmpty();
The Open/Closed Principle [usually attributed to Bertrand Meyer] says that "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification". This might be the principle that you came across in your Java days. In real life this applies to completed code where the cost of modification, re-testing and re-certification outweighs the benefit of the simplicity gained by making a direct change.
If you are changing a method because it needs an additional argument, you might choose to use the following steps:
Copy the old method.
Remove the implementation from the copy.
Change the signature of the original method to add the new argument.
Update the implementation of the original method to use the new argument.
Implement the copy in terms of the new method with a default value for the argument.
If your implementation language doesn't support method overloading then the principle is the same but you need to find a new name for the new method signature.
The advantage of this approach is that you have added the new argument to the method, and your existing client code will continue to compile and run.
This works well if there is an obvious default for the new argument, and less well if there isn't.
Since java 5 you can use variable list of arguments as in void foo(Object ... params)
You will need to come up with creative names for your methods since you can't overload methods that have same type and number of arguments (or based on return type). I actually personally prefer this to overloading anyway. So you can have isEmpty and isEmptyWhenFoo and isEmptyWhenIHaveTheseArguments (well meybe not the last one :)
Not sure if this actually answers your question, but the best way to think about OO in "real life" is to think of the Nygaard Classification:
ObjectOrientedProgramming. A program execution is regarded as a physical model, simulating the behavior of either a real or imaginary part of the world.
So how would you build a physical device to do what you are trying to do in code? You'd probably have some kind of "Form" object, and the form object would have little tabs or bits connected to it to represent the different Form variables, and then you would build a Validator object that would take the Form object in a slot and then flash one light if the form was valid and another if it was invalid. Or your Validator could take a Form object in one slot and return a Form object out (possibly the same one), but modified in various ways (that only the Validator understood) to make it "valid". Or maybe a Validator is part of a Form, and so the Form has this Validator thingy sticking out of it...
My point is, try to imagine what such a machine would look like and how it would work. Then think of all of the parts of that machine, and make each one an object. That's how "object-oriented" things work in "real life", right?
With that said, what is meant by "extending" a class? Well, a class is a "template" for objects -- each object instance is made by building it from a class. A subclass is simply a class that "inherits" from a parent class. In Java at least, there are two kinds of inheritance: interface inheritance and implementation inheritance. In Java, you are allowed to inherit implementation (actual method code) from at most one class at a time, but you can inherit many interfaces -- which are basically just collections of attributes that someone can see from outside your class.
Additionally, a common way of thinking about OO programming is to think about "messages" instead of "method calls" (in fact, this is the original term invented by Alan Kay for Smalltalk, which was the first language to actually be called "object-oriented"). So when you send an isEmpty message to the object, how do you want it to respond? Do you want to be able to send different arguments with the isEmpty message and have it respond differently? Or do you want to send the isEmpty message to different objects and have them respond differently? Either are appropriate answers, depending on the design of your code.
Instead having one class providing multiple versions of isEmpty with differing names, try breaking down your model into a finer grained pieces the could be put together in more flexible ways.
Create an interface called Empty with
one method isEmpty(String value);
Create implemntations of this
interface like EmptyIgnoreWhiteSpace
and EmptyIgnoreZero
Create FormField
class that have validation methods
which delegate to implementations of
Empty.
Your Form object will have
instances of FormField which will
know how to validate themselves.
Now you have a lot of flexibility, you can combine your Empty implemenation classes to make new classes like EmptyIgnoreWhiteSpaceAndZero. You can use them in other places that have nothing to do with form field validation.
You don't have have have multple similarly named methods polluting your object model.

Use of helper/utility methods in a Factory class

I have a question about the usage of "utility/helper" methods in a factory class. Consider an example of an XML string that reprents a document. I have a class that transforms it to an "object" (say PDF, Word, CSV, etc.). I have a factory class (lets call it DocumentFactory) that accepts this XML string and based on certain rules gives back the correct document object.
My question here is that in terms of "best practices" is it ok for me to add "utility/helper" methods to the DocumentFactory class that aid in deciding that type of object will be returned? These helpers are beyond simple if/swtich case statements. But not more than 15-20 lines.
I am using one private static class as well in my code and there are about 4-5 helper methods (the helpers are public since I have tests written for these).
So is this setup a valid one for a factory class?
No, there is nothing intrinsically wrong with using helper methods in a Factory to help decide what sort of object to return. All the usual method-related warnings apply, but there are no Factory-specific reasons to avoid them.
This is perfectly fine.. In fact, I'd say that using helper methods is the preferred way of doing it, since it is good practice to chunk up your code into as many re-usable methods as possible. You should probably make these helper methods private (and static, assuming the factory method itself is static).

junit & java : testing non-public methods [duplicate]

This question already has answers here:
How do I test a class that has private methods, fields or inner classes?
(58 answers)
Closed 5 years ago.
JUnit will only test those methods in my class that are public. How do I do junit testing on the ones that are not (i.e., private, protected)?
I can test them by not using junit, but I was wondering what the junit standard method was.
One school of thought about unit testing says that you should only be able to test public methods, because you should only be unit-testing your public API, and that by doing so, you should be covering the code in your non-public methods. Your mileage may vary; I find that this is sometimes the case and sometimes not.
With that said, there are a couple of ways to test non-public methods:
You can test protected and package-scope methods by putting your unit tests in the same package as the classes they're testing. This is a fairly common practice.
You can test protected methods from unit tests in another package by creating a subclass of the class under test that overrides the methods you want to test as public, and having those overridden methods call the original methods with the super keyword. Typically, this "testing subclass" would be an inner class in the JUnit TestCase class doing the testing. This is a little bit more hacky, in my opinion, but I've done it.
As with many unit testing problems, testing private methods is actually a design problem in disguise. Rather than try to do anything tricky to test private methods, when I find myself wishing to write tests for private methods I take a minute to ask myself, "How would I need to design this so I could test it thoroughly through public methods?"
If that doesn't work, JUnitX allows testing private methods, although I believe it is only available for JUnit 3.8.
When you write a JUnit test, you have to do a subtle mind shift: "I'm a client of my own class now." That means private is private, and you only test the behavior that the client sees.
If the method really should be private, I'd consider it a design flaw to make it visible just for the sake of testing. You've got to be able to infer its correct operation based on what the client sees.
In the three years that have passed since I originally wrote this, I've started approaching the problem slightly differently, using Java reflection.
The dirty little secret is that you can test private methods in JUnit just as you would public ones, using reflection. You can test to your heart's content and still not expose them as public to clients.
The simplest solution is to put the JUnit tests in the same package (but different directory) and use default (i.e. package-private) visibility for the methods.
Another more complicated approach is to use reflection to access private methods.
If you have a significant amount of logic buried under relatively few "Public" entry points, you are probably violating the Single Responsibility Principle. If possible, you'll want to refactor the code into multiple classes, ultimately leading to more "Public" methods from which to test.
Here is the "probably shouldn't do it this way" method that everyone else keeps harping at you about. I think it's certainly within the realm of possibility that there are reasons for doing it this way, though. The following code will access a private field, but the code for a private method is nearly identical.
public void testPrivateField() throws InterruptedException {
Class<ClassWPrivateField> clazz = ClassWPrivateField.class;
try {
Field privateField = clazz.getDeclaredField("nameOfPrivateField");
privateField.setAccessible(true); // This is the line
// do stuff
} catch(NoSuchFieldException nsfe) {
nsfe.printStackTrace();
fail();
} catch(IllegalAccessException iae) {
iae.printStackTrace();
fail();
}
}
I've come across the same issue, and the "if it needs to be private it probably should be refactored" doesn't sit right with me.
Suppose you have sort of functionality that you want to separate out in some way internal to the class. For example, suppose I have something like this:
public class HolderOfSomeStrings{
private List<String> internal_values;
public List<String> get()
{
List<String> out = new ArrayList<String>();
for (String s:internal_values)
{
out.add(process(s));
}
return get;
}
private static String process(String input)
{
//do something complicated here that other classes shouldn't be interested in
}
}
The point here is that junit forces me to make process public, or at least protected, or to put it in it's own utility class. But if it's some sort of internal logic of HolderOfSomeStrings, it's not at all clear to me that this is correct—it seems to me that this ought to be private, and making it more visible gums up the code in some way.
I nearly always use Spring in my Java projects and, as such, my objects are built for dependency injection. They tend to be fairly granular implementations of public interfaces that are assembled within the application context. As such, I rarely (if ever) have the need to test private methods because the class itself is small enough that it simply isn't an issue.
Even when I don't use Spring I tend to adopt the same practices of assembling small and simple objects into larger and larger abstractions, each of which is relatively simple but made complex by the aggregated objects.
In my experience, having the need to unit test private methods is an indicator that what you're teesting could (and should) be simplified.
That being, if you still really feel the need:
Protected methods can be tested by subclasses;
Package private methods can be tested by putting the unit tests in the same package; and
Private methods can be unit tested by providing, for example, a package private factory proxy method. Not ideal but private does mean private.
You usually don't test private methods because they can only (normally) be tested indirectly through another public method. When you're test driving and make private methods then they are usually a result of an "extract method" refactoring and are already by then tested indirectly.
If you are concerned about testing a private method with lots of logic then the smartest thing you could do is to move that code into another class in a public method. Once you've done that, the previous method that used this code can have it's testing simplified by having the functionality provided by a stub or a mock.
To borrow a thought from Andy Hunt, even your private methods must have some side effect that you're interested in. In other words, they must be called from some public method and perform an interesting task that causes the state of your object to change. Test for that state change.
Suppose you have public method pubMethod and private method privMethod. When you call pubMethod, it in turn calls privMethod to perform a task (perhaps parsing a String). The pubMethod then uses this parsed String to set member variables' values in some way or to influence its own return value. Test by watching for the desired effect on pubMethod's return value or on member variables (possibly by using accessors to get to them).
DP4j Jar
For testing private methods we need to use reflection and its pointed in all answers.
well now this task is simplified with help of Dp4j jar.
Dp4j analyzes your code and automatically generates the Reflection API code for you.
Just add dp4j.jar to your CLASSPATH.
Dp4j.jar contains Annotation Processors, they will look for the methods in your code that are annotated with #Test JUnit annotation.
Dp4j analyze the code of those methods, and if it finds that you are illegally accessing private methods, it will replace your invalid private method reference with equivalent code that uses Java's Reflection API.
Get More details here
You can use TestNG instead of JUnit, which doesn't care about the method being private or public.
Use reflection as above to test private methods.
If we are following TDD we should test private methods given that TDD implies that there would be no surprises later.
So one should not wait to finish his public method to test privates.
And this helps in more granular regression testing upon re factoring.
Look for "PrivateAccessor.invoke". My code imports it from "junitx.util", but I don't know where it came from.
In agreement with just about every post--you should probably refactor and probably not test private except through public, just wanted to add a different way to think about it...
Think of your class itself as a "Unit", not a method. You are testing the class and that it can maintain a valid state regardless of how it's public methods are called.
Calling private methods can destroy the encapsulation and actually invalidate the tests.
As kind of an offshoot of this, and I'm not sure where everyone comes down on the whole "polyglot programming" issue, but Groovy tests are runnable in Junit, and ignore the whole public/non-public issue. Side note, it was officially classified as a "bug", but when they tried to fix it, there was such a storm kicked up about it that it was put back as it was originally.
I absolutely agree with #duffymo that code should be tested from the client's view ( though he says he quit thinking this way). However, from this point of view, private vs others have different meanings. Client of a private method is the class itself so I prefer testing them through the external (public/package-protected) API. However, protected and package-protected members are there for external clients, so I test them with fakes which inherit the owning class or which reside in the same package.

Categories

Resources