Related
I want to ask which implementation is better. I think the first method is better because when I read this method, I know this method return personId, it's more readable than the second one. is it right?
Method 1:
public String persistPerson(Person person) {
String personId = persistService.persist(person);
return personId;
}
Method 2:
public String persistPerson(Person person) {
return persistService.persist(person);
}
The first method is pretty readable. You could split it up into two small setter and getter methods if you want to make it even easier to understand.
I would suggest you use javadocs to document your code if your intention is to later explain what everything does.
Every con has two sides so as your program because both the defination has one advantage over other.
For 1st method:-
Advantage: : It is more readable as the other person comes to understand very quickly that what it returns.
Disadvantage : :- As you formulate a new string it will use some space to create new string so wastage of memory.
For 2nd method:-
Advantage :- It avoids wastage of memory.
Disadvantage :- Its not readable
The first way is really better. When other guys look at this code, they immediately know what is the returned value. In contrast they must read java doc to know what is returned in the second way.
While unit testing some methods, there can be some scenarios where value of some parameters do not matter and can be any value.
For example in this piece of code:
public void method(String arg1, String arg2, int arg3){
if(arg1 == null) throw new NullPointerException("arg1 is null");
//some other code
}
unit testing the behavior that when arg1 is null then NPE must be thrown, the values of other arguments do not matter, they can be any value or be null.
So I wanted to document the fact that the values do not matter for the method under test.
I thought of following options:
Option 1: Define constants of ANY_XXX
I thought of explicitly creating constants ANY_STRING and ANY_INT, which contain a fixed value which documents that it can be any value and the method under test does not care about the actual value.
I can put all these constants in a single class called Any and reuse them across all test classes.
Option 2: Random values for ANY_XXX
This option seems a bit hacky to me as I have read somewhere that randomness should not be brought into test cases. But in this scenario this randomness will not be visible as the parameters will not create any side effect.
Which approach would be more suitable for better, readable tests?
UPDATE:
While I can use ANY_XXX approach by defining constants in Any class, but I am also thinking of generating ANY_XXX values with some constraints such as
Any.anyInteger().nonnegative();
Any.anyInteger().negative();
Any.anyString().thatStartsWith("ab");
I am thinking that maybe Hamcrest Matchers can be used for creating this chaining. But I am not sure if this approach is a good one. Similar methods for anyObject() are already provided by Mockito but those only work on Mocks and spies and not on normal objects. I want to achieve the same for normal objects for more readable tests.
Why I want to do this?
Suppose I have a class
class MyObject{
public MyObject(int param1, Object param2){
if(param1 < 0) throw new IllegalArgumentException();
if(param2 == null) throw new NullPointerException();
}
}
And now while writing tests for constructor
class MyObjectTest{
#Test(expected=NullPointerException.class)
public void testConstructor_ShouldThrowNullpointer_IfSecondParamIsNull(){
//emphasizing the fact that value of first parameter has no relationship with result, for better test readability
new MyObject(Any.anyInteger().nonnegative(), null);
}
}
I see both og them quite a lot
Personally I disagree that randomness should not be brought into tests. Using randomness to some degree should make your tests more robust, but not necessarily easier to read
If you go for the first approach I would not create a constants class, but rather pass the values (or nulls) directly, since then you see what you pass in without the need to have a look in another class - which should make your tests more readable. You can also easily modify your tests later if you need the other parameters later on
My preference is to build up a utility class of constants along with methods to help with the creation of the constant values for tests, e.g.:
public final class Values {
public static final int ANY_INT = randomInt(Integer.MIN_VALUE, Integer.MAX_VALUE);
public static final int ANY_POSITIVE_INT = randomInt(0, Integer.MAX_VALUE);
public static final String ANY_ISBN = randomIsbn();
// etc...
public static int randomInt(int min, int max) { /* omitted */ }
public static String randomIsbn() { /* omitted */ }
// etc...
}
Then I would use static imports to pull the constants and methods I needed for a particular test class.
I use the ANY_ constants only in situations where I do not care about the value, I find that they can make the intent of the test clearer, for example:
// when
service.fooBar(ANY_INT, ANY_INT, ANY_INT, ANY_INT, 5);
It's clear that the value 5 is of some significance - although it would be better as a local variable.
The utility methods can be used for adhoc generation of values when setting up tests, e.g.:
// given
final String isbn1 = randomIsbn();
final String isbn2 = randomIsbn();
final Book[] books = { new Book(isbn1), new Book(isbn2) };
// when
bookRepository.store(books);
Again, this can help to keep the test classes concerned about the tests themselves and less about data set up.
In addition to this I have also used a similar approach from domain objects. When you combine the two approaches it can be quite powerful. e.g.:
public final class Domain {
public static Book book() {
return new Book(randomIsbn());
}
// etc...
}
I've faced the same problem when i've started to write unit tests for my project and had to deal with numerous of arrays, lists, integer inputs, strings etc.
So I decided to use QuickCheck and create a generator util class.
Using Generators in this library, you can generate primitive data types and String easily.
For example, when you want to Generate an integer; simply use IntegerGenerator class.You can define maximum and minimum values in the constructor of the generator.You can also use CombinedGeneratorSamples class to generate data structures like lists, maps and arrays.
Another feature of this library is implementing Generator interface for custom class generators.
You're overthinking and creating unnecessary barriers for your project :
if you want to document your method, do it with words! that's why the Javadoc is here for
if you want to test your method with "any positive int" then just call it with a couple different positive ints. In your case, ANY does not mean testing every possible integer value
if you want to test your method with "a string that starts with ab", call it with "abcd", then "abefgh" and just add a comment on the test method !
Sometimes we are so caught with frameworks and good practices that it takes common sense away.
In the end : most readable = simplest
How about using a caller method for the actual method.
//This is the actual method that needs to be tested
public void theMethod(String arg1, String arg2, int arg3, float arg4 ){
}
Create a caller method that calls the method with the required parameters and default(or null) values for the rest of the params and run your test case on this caller method
//The caller method
#Test
public void invokeTheMethod(String param1){
theMethod(param1, "", 0, 0.0F); //Pass in some default values or even null
}
Although you will have to be pretty sure that passing default values on theMethod(...) for the other parameters wont cause any NPE.
i see 3 options:
never pass nulls, forbid your team passing nulls. nulls are evil. passing null should be an exception, not a rule
simply use annotation in production code: #NotNull or sth like that. if u use lombok, this annotation will also do the actual validation
and if u really have to do it in tests then simply create a test with proper name:
static final String ANY_STRING = "whatever";
#Test
public void should_throw_NPE_when_first_parameter_is_null() {
object.method(null, ANY_STRING, ANY_STRING); //use catch-exception or junit's expected
}
If you're willing to give JUnitParams' framework a go, you could parametrize your tests specifying meaningful names to your parameters:
#Test
#Parameters({
"17, M",
"2212312, M" })
public void shouldCreateMalePerson(int ageIsNotRelevant, String sex) throws Exception {
assertTrue(new Person(ageIsNotRelevant, sex).isMale());
}
I'm always in favor of the constants approach. The reason is that I believe it gets more readable than chaining several matchers.
Instead of your example:
class MyObjectTest{
#Test(expected=NullPointerException.class)
public void testConstructor_ShouldThrowNullpointer_IfSecondParamIsNull(){
new MyObject(Any.anyInteger().nonnegative(), null);
}
}
I would d:
class MyObjectTest{
private static final int SOME_NON_NEGATIVE_INTEGER = 5;
#Test(expected=NullPointerException.class)
public void testConstructor_ShouldThrowNullpointer_IfSecondParamIsNull(){
new MyObject(SOME_NON_NEGATIVE_INTEGER, null);
}
}
Also, I prefer the use of 'SOME' over 'ANY', but that's also a matter of personal taste.
If you're considering testing the constructor with a number of different variants as you mentioned (nonNegative(), negative(), thatStartsWith(), etc.), I would that instead you write parameterized tests. I recommend JUnitParams for that, here's how I'd do it:
#RunWith(JUnitParamRunner.class)
class MyObjectTest {
#Test(expected = NullPointerException.class)
#Parameters({"-4000", "-1", "0", "1", "5", "10000"})
public void testConstructor_ShouldThrowNullpointer_IfSecondParamIsNull(int i){
new MyObject(i, null);
}
...
}
I suggest you go with constant values for those parameters which may be arbitrary. Adding randomness makes your test runs not repeatable. Even if parameter values "don't matter" here, actually the only "interesting" case is when a test fails, and with random behavior added in, you might not be able to reproduce the error easily. Also, simpler solutions are often better, and easier to maintain: using a constant is certainly simpler than using random numbers.
Of course if you go with constant values, you could put these values in static final fields, but you could also put them in methods, with names such as arbitraryInt() (returning e.g. 0) and so on. I find the syntax with methods cleaner than with constants, as it resembles Mockito's any() matchers. It also allows you to replace the behavior more easily in case you need to add more complexity later on.
In case you want to indicate that a parameter doesn't matter and the parameter is an object (not primitive type), you can also pass empty mocks, like so: someMethod(null, mock(MyClass.class)). This conveys to a person reading the code that the second parameter can be "anything", since a newly created mock has only very basic behavior. It also doesn't force you to create your own methods for returning "arbitrary" values. The downside is it doesn't work for primitive types or for classes which can't be mocked, e.g. final classes like String.
Ok.... I see a big Problem with you approach!
The other value doesn't matter? Who guarantees this? The Writer of the Test, the writer of the Code? What if you have a Method, which throws some unrelated Exception if the first Parameter is exactly 1000000 even if the second parameter is NULL ?
You have to formulate your Test-Cases: What is the Test-Specification... What do you want to proof? Is it:
In some cases if the first parameter is some arbitrary value and the second is null, this method should throw a NullPointerException
For any possible first Input value, if the second value is NULL the method should always throw a NullPointerException
If you want to test the first case - your approach is ok. Use a constant, a random value, a Builder... whatever you like.
But if your specification actually requires the 2nd condition all of your presented solutions are not up for the task, since they only test some arbitrary value. A good test should still be valid if the programmer changes some code in the method. This means the right way to test this method would be a whole series of Testcases, testing all corner-cases as with all other methods. So each critical value which can lead to a different execution-path should be checked - or you need a testsuite which checks for code-path completeness...
Otherwise your test is just bogus and there to look pretty...
I'm still coming to terms with unit testing certain things and I have a question about my JUnit test for a relatively simple class:
public class Kite {
private List<String> strings = new ArrayList<String>();
public void addString(String string) { //... }
public void removeString(String string) { //... }
public List<String> getStrings() { //... }
public int getNumStrings() { //... }
}
In this case I would like to test all four methods. However the tests, now that I've written them, are all very similar. They (excluding the remove) all follow the basic structure of add a String to a Kite and then checking the number of Strings in the Kite object.
Is there a better way to test these "CRUD" types of methods?
Do I need to test them?
It's better to be more specific in your testing. For addString(), you want to test that:
The string you added is present in the collection.
No other strings were added to the collection as a side effect.
If you pass null to addString(), an IllegalArgumentException (or whatever the behavior should be) is thrown
If you pass the same string in twice, the behavior is what you want (could be an IllegalArgumentException, could be a no-op)
get the idea? You want to add tests for edge cases, as well as the normal behavior (sometimes called the "happy path"). Think about your tests in terms of possible inputs, possible outputs, and code paths that can be taken.
I would think about writing one test that models a transaction:
Check the pre-condition.
Perform add operation.
Check post-condition.
Rollback add operation with remove.
Make sure that Kite is in original state.
All those methods will be tested that way.
I was reading an article that said that Java strings are not completely immutable. However, in the article's sample code that modifies the string, it makes a call to string.toUpperCase().toCharArray(), which returns a new string. So what's the purpose of going through the process of changing the string if you call toUpperCase() anyway? Here is the code:
public static void toUpperCase(String orig)
{
try
{
Field stringValue = String.class.getDeclaredField("value");
stringValue.setAccessible(true);
stringValue.set(orig, orig.toUpperCase().toCharArray());
}
catch (Exception ex){}
}
Also, I noticed that string.toUpperCase() by itself doesn't work. It needs to be string.toUpperCase().toCharArray(). Is there a reason for this?
What he's doing:
He's acquring some character array that he knows is the right length (such as the uppercase version of the String) and putting it as the backing array of the String. (The backing array is called value inside the String class.)
Why he's doing it:
To illustrate that you could put any char array there you wanted.
Why this is useful:
String is immutable, and this allows you to circumvent the immutability. Of course, this is not recommended to do - EVER. On the contrary, I would not be surprised if he was saying "Watch out, because people could potentially do this to YOUR code. Even if you think your stuff is safe, it might not be!"
The implications of this are wide reaching. Immutable variables are no longer immutable. Final variables are no longer final. Thread safe objects are no longer thread safe. Contracts you thought you could rely upon, you can no longer do so. All because some engineer somewhere had a problem he couldn't fix with normal means, so he delves into reflection to solve it. Don't be 'that guy'.
You'll also note that how the hashCode for that String would now be changed. So, if you've never calculated the hashCode for that String, it's still 0 so you're okay. On the other hand, if you have calculated it, when you go to put it in a HashMap or HashSet, it won't be retrieved.
Consider the following:
import java.util.*;
import java.lang.reflect.*;
class HashTest {
/** Results:
C:\Documents and Settings\glowcoder\My Documents>java HashTest
Orig hash: -804322678
New value: STACKOVERFLOW
Contains orig: true
Contains copy: false
*/
public static void main(String[] args) throws Exception {
Set<String> set = new HashSet<String>();
String str = "StackOverflow";
System.out.println("Orig hash: " + str.hashCode());
set.add(str);
Field stringValue = String.class.getDeclaredField("value");
stringValue.setAccessible(true);
stringValue.set(str, str.toUpperCase().toCharArray()); //
System.out.println("New value: " + str);
String copy = new String(str); // force a copy
System.out.println("Contains orig: " + set.contains(str));
System.out.println("Contains copy: " + set.contains(copy));
}
}
I would bet he is doing this as a warning against bad behavior rather than showing a 'cool' trick.
EDIT: I found the article you're referring to, and the article it is based on. The original article states: "This means that if a class in another package "fiddles" with an interned String, it can cause havoc in your program. Is this a good thing? (You don't need to answer ;-) " I think that makes it quite clear this is more of a protection guide than advice on how to code.
So if you walk away from this thread with only one piece of information, it is that reflection is dangerous, unreliable, and not to be trifled with!
Don't try this at home!
You are subverting String's immutability. There is no good reason to do this.
I think I cannot add to the explanations already provided, so perhaps I can add to the discussion by suggesting how this can be prevented.
You can prevent somebody tampering with your code in these and other unintended ways by means of using a security manager.
public static void main(String args[]){
System.setSecurityManager(new SecurityManager());
String jedi1 = "jedi";
toUpperCase(jedi1);
System.out.println(jedi1);
}
This will generate an exception in the toUpperCase method, provided that you are not granting all privileges to all code bases in the default policy files. (In your current code your exceptions are currently swallowed).
What is the purpose? I'm not sure, ask the one that wrote this stuff. You normally should not do something like this. There is a reason String is immutable.
Here how this method would look if the fields were public, i.e. without reflection:
public static void toUpperCase(String orig) {
orig.value = orig.toUpperCase().toCharArray();
}
As value is of type char[], you can't assign a String to this field - this is why you need the toCharArray call after .toUpperCase(). You will get an exception if you try to do this (I suppose ClassCastException), but the try-catch block there eats it away. (This gets us another lesson: Never use such empty catch blocks.)
Pay attention: This code might not do the correct thing, since the actual data of the original string might not start at the start of the char[]. Since you don't update the offset field, you will get IndexOutOfBoundsExceptions when using such a modified String. Also, the String object caches its hashCode, thus this will be wrong, too.
Here would be a correct way:
public static void toUpperCase(String orig) {
orig.value = orig.toUpperCase().toCharArray();
orig.offset = 0;
orig.hash = 0; // will be recalculated on next `.hashCode()` call.
}
With reflection, it looks like this:
public static void toUpperCase(String orig)
{
try
{
Field stringValue = String.class.getDeclaredField("value");
stringValue.setAccessible(true);
stringValue.set(orig, orig.toUpperCase().toCharArray());
Field stringOffset = String.class.getDeclaredField("offset");
stringOffset.setAccessible(true);
stringOffset.setInt(orig, 0);
Field stringHash = String.class.getDeclaredField("hash");
stringHash.setAccessible(true);
stringHash.setInt(orig, 0);
}
catch (Exception ex){
// at least print the output
ex.printStackTrace();
}
}
1.) Read Bohemian answer.
2.) Strings are internally stored in a char array, that's why you need to call toCharArray to set the field.
By default, String.toUpperCase() leaves the original string intact, whilst returning a new string object.
The function you defined above, edits the contents of the original string object in-place.
You change a final string with reflection for testing. Sometimes that string contains the path to a default location used in the production environment but not suitable for testing. Yet, that variable is referenced by several objects/methods your trigger in your test, and hence during your tests you might want to set it to a particular value.
As others said, it's probably something you don't want to be doing (often/ever).
Functions (side-effect free ones) are such a fundamental building block, but I don't know of a satisfying way of testing them in Java.
I'm looking for pointers to tricks that make testing them easier. Here's an example of what I want:
public void setUp() {
myObj = new MyObject(...);
}
// This is sooo 2009 and not what I want to write:
public void testThatSomeInputGivesExpectedOutput () {
assertEquals(expectedOutput, myObj.myFunction(someInput);
assertEquals(expectedOtherOutput, myObj.myFunction(someOtherInput);
// I don't want to repeat/write the following checks to see
// that myFunction is behaving functionally.
assertEquals(expectedOutput, myObj.myFunction(someInput);
assertEquals(expectedOtherOutput, myObj.myFunction(someOtherInput);
}
// The following two tests are more in spirit of what I'd like
// to write, but they don't test that myFunction is functional:
public void testThatSomeInputGivesExpectedOutput () {
assertEquals(expectedOutput, myObj.myFunction(someInput);
}
public void testThatSomeOtherInputGivesExpectedOutput () {
assertEquals(expectedOtherOutput, myObj.myFunction(someOtherInput);
}
I'm looking for some annotation I can put on the test(s), MyObject or myFunction to make the test framework automatically repeat invocations to myFunction in all possible permutations for the given input/output combinations I've given, or some subset of the possible permutations in order to prove that the function is functional.
For example, above the (only) two possible permutations are:
myObj = new MyObject();
myObj.myFunction(someInput);
myObj.myFunction(someOtherInput);
and:
myObj = new MyObject();
myObj.myFunction(someOtherInput);
myObj.myFunction(someInput);
I should be able to only provide the input/output pairs (someInput, expectedOutput), and (someOtherInput, someOtherOutput), and the framework should do the rest.
I haven't used QuickCheck, but it seems like a non-solution. It is documented as a generator. I'm not looking for a way to generate inputs to my function, but rather a framework that lets me declaratively specify what part of my object is side-effect free and invoke my input/output specification using some permutation based on that declaration.
Update: I'm not looking to verify that nothing changes in the object, a memoizing function is a typical use-case for this kind of testing, and a memoizer actually changes its internal state. However, the output given some input always stays the same.
If you are trying to test that the functions are side-effect free, then calling with random arguments isn't really going to cut it. The same applies for a random sequence of calls with known arguments. Or pseudo-random, with random or fixed seeds. There's a good chance are that a (harmful) side-effect will only occur with any of the sequence of calls that your randomizer selects.
There is also a chance that the side-effects won't actually be visible in the outputs of any of the calls that you are making ... no matter what the inputs are. They side-effects could be on some other related objects that you didn't think to examine.
If you want to test this kind of thing, you really need to implement a "white-box" test where you look at the code and try and figure out what might cause (unwanted) side-effects and create test cases based on that knowledge. But I think that a better approach is careful manual code inspection, or using an automated static code analyser ... if you can find one that would do the job for you.
OTOH, if you already know that the functions are side-effect free, implementing randomized tests "just in case" is a bit of a waste of time, IMO.
I'm not quite sure I understand what you are asking, but it seems like Junit Theories (http://junit.sourceforge.net/doc/ReleaseNotes4.4.html#theories) could be an answer.
In this example, you could create a Map of key/value pairs (input/output) and call the method under test several times with values picked from the map. This will not prove, that the method is functional, but will increase the probability - which might be sufficient.
Here's a quick example of such an additional probably-functional test:
#Test public probablyFunctionalTestForMethodX() {
Map<Object, Object> inputOutputMap = initMap(); // this loads the input/output values
for (int i = 0; i < maxIterations; i++) {
Map.Entry test = pickAtRandom(inputOutputMap); // this picks a map enty randomly
assertEquals(test.getValue(), myObj.myFunction(test.getKey());
}
}
Problems with a higher complexity could be solved based on the Command pattern: You could wrap the test methods in command objects, add the command object to a list, shuffle the list and execute the commands (= the embedded tests) according to that list.
It sounds like you're attempting to test that invoking a particular method on a class doesn't modify any of its fields. This is a somewhat odd test case, but it's entirely possible to write a clear test for it. For other "side effects", like invoking other external methods, it's a bit harder. You could replace local references with test stubs and verify that they weren't invoked, but you still won't catch static method calls this way. Still, it's trivial to verify by inspection that you're not doing anything like that in your code, and sometimes that has to be good enough.
Here's one way to test that there are no side effects in a call:
public void test_MyFunction_hasNoSideEffects() {
MyClass systemUnderTest = makeMyClass();
MyClass copyOfOriginalState = systemUnderTest.clone();
systemUnderTest.myFunction();
assertEquals(systemUnderTest, copyOfOriginalState); //Test equals() method elsewhere
}
It's somewhat unusual to try to prove that a method is truly side effect free. Unit tests generally attempt to prove that a method behaves correctly and according to contract, but they're not meant to replace examining the code. It's generally a pretty easy exercise to check whether a method has any possible side effects. If your method never sets a field's value and never calls any non-functional methods, then it's functional.
Testing this at runtime is tricky. What might be more useful would be some sort of static analysis. Perhaps you could create a #Functional annotation, then write a program that would examine the classes of your program for such methods and check that they only invoke other #Functional methods and never assign to fields.
Randomly googling around, I found somebody's master's thesis on exactly this topic. Perhaps he has working code available.
Still, I will repeat that it is my advice that you focus your attention elsewhere. While you CAN mostly prove that a method has no side effects at all, it may be better in many cases to quickly verify this by visual inspection and focus the remainder of your time on other, more basic tests.
have a look at http://fitnesse.org/: it is used often for Acceptance Test but I found it is a easy way to run the same tests against huge amount of data
In junit you can write your own test runner. This code is not tested (I'm not sure if methods which get arguments will be recognized as test methods, maybe some more runner setup is needed?):
public class MyRunner extends BlockJUnit4ClassRunner {
#Override
protected Statement methodInvoker(final FrameworkMethod method, final Object test) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
Iterable<Object[]> permutations = getPermutations();
for (Object[] permutation : permutations) {
method.invokeExplosively(test, permutation[0], permutation[1]);
}
}
};
}
}
It should be only a matter of providing getPermutations() implementation. For example it can take data from some List<Object[]> field annotated with some custom annotation and produce all the permutations.
I think the term you're missing is "Parametrized Tests". However it seems to be more tedious in jUnit that in the .Net flavor. In NUnit, the following test executes 6 times with all combinations.
[Test]
public void MyTest(
[Values(1,2,3)] int x,
[Values("A","B")] string s)
{
...
}
For Java, your options seem to be:
JUnit supports this with version 4. However it's a lot of code (it seems, jUnit is adamant about test methods not taking parameters). This is the least invasive.
DDSteps, a jUnit plugin. See this video that takes values from appropriately named excel spreadsheet. You also need to write a mapper/fixture class that maps values from the spreadsheet into members of the fixture class, that are then used to invoke the SUT.
Finally, you have Fit/Fitnesse. It's as good as DDSteps, except for the fact that the input data is in HTML/Wiki form. You can paste from an excel sheet into Fitnesse and it formats it correctly at the push of a button. You need to write a fixture class here too.
Im afraid that I dont find the link anymore, but Junit 4 has some help functions to generate testdata. Its like:
public void testData() {
data = {2, 3, 4};
data = {3,4,5 };
...
return data;
}
Junit will then thest your methods will this data. But as I said, I cant' find the link anymore (forgot the keywords) for a detailed (and correct) example.