Given the following code:
LinkedList list = mock(LinkedList.class);
doCallRealMethod().when(list).clear();
list.clear();
by executing this test, a NullPointerException is thrown from first line in LinkedList#clear:
public void clear() {
Entry<E> e = header.next;
while (e != header) {
Entry<E> next = e.next;
//Code omitted.
but header has been instantiated before:
private transient Entry<E> header = new Entry<E>(null, null, null);
Could someone please explain what's happening during mock creation?
####### UPDATE. ######
Having read all answers especially Ajay's one, I looked into Objenesis source code and find out that it's using Reflection API to create the proxy instance (through CGLIB) and therefore bypassing all constructors in the hierarchy until java.lang.Object.
Here is the sample code to simulate the issue:
public class ReflectionConstructorTest {
#Test
public void testAgain() {
try {
//java.lang.Object default constructor
Constructor javaLangObjectConstructor = Object.class
.getConstructor((Class[]) null);
Constructor mungedConstructor = ReflectionFactory
.getReflectionFactory()
.newConstructorForSerialization(CustomClient.class, javaLangObjectConstructor);
mungedConstructor.setAccessible(true);
//Creates new client instance without calling its constructor
//Thus "name" is not initialized.
Object client = mungedConstructor.newInstance((Object[]) null);
//this will print "CustomClient"
System.out.println(client.getClass());
//this will print "CustomClient: null". name is null.
System.out.println(client.toString());
} catch(Exception e) {
e.printStackTrace();
}
}
}
class CustomClient {
private String name;
CustomClient() {
System.out.println(this.getClass().getSimpleName() + " - Constructor");
this.name = "My Name";
}
#Override
public String toString() {
return this.getClass().getSimpleName() + ": " + name;
}
}
You are only asking Mockito to call the real thing on clear, the underlying object is still a fake created by Mockito for you. If you need a real LinkedList then just use the LinkedList - only the most heated purist of BDD would tell you to mock everything around you. I mean, you are not mocking Strings are you?
Mockito author himself has said that calling the real thing should be used scarcely, usually only for testing a legacy code.
If you need to spy on the real object (track the invocations) then Mockito has a feature for this too:
List list = new LinkedList();
List spy = spy(list);
With spy, you can still stub a method if you need. It basically works like a mock, but isn't ;)
Your reasoning is flawless.
The key issue is that you are not operating on the actual LinkedList object. Here is what is happening behind the scenes:
The object that you are given by Mockito's mock() is an Enhancer object from the CGLIB library.
For me it is something like java.util.LinkedList$$EnhancerByMockitoWithCGLIB$$cae81a28
which kind of acts like a Proxy, albeit with the fields set to default values. (null,0 etc)
When you mock a class the object you are using is a fake, therefore the variables are not instantiated and the methods don't work as expected. You could use reflection to set a value for the header but I really wouldn't recommend this. As theadam said, the best thing to do would be to just use a list.
Related
I've been searching for the answer to "how to add an annotation to the method at runtime" for several days already and found this awesome tool called Byte Buddy, played with it, but still cannot make it work as I need to. I'm sure it must be able to do that from this question Can Byte Buddy create fields and method annotations at runtime?
Having this class:
public class ClassThatNeedsToBeAnnotated {
public void method(int arg1, String arg2) {
// code that we don't want to touch at all, leave it as is
System.out.println("Called method with arguments " + arg1 + " " + arg2);
}
public void method() {
System.out.println("Called method without arguments");
}
}
and this code:
public class MainClass {
public static void main(String[] args) {
ByteBuddyAgent.install();
AnnotationDescription description = AnnotationDescription.Builder.ofType(MyClassAnnotation.class)
.define("value", "new")
.build();
new ByteBuddy()
.redefine(ClassThatNeedsToBeAnnotated.class)
.annotateType(description)
.make()
.load(ClassThatNeedsToBeAnnotated.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
}
}
It is easy to add an annotation to the class.
But for the method, it seems to be not possible without changing the method implementation.
Method existingMethod = ClassThatNeedsToBeAnnotated.class.getDeclaredMethods()[0];
AnnotationDescription annotationDescription = AnnotationDescription.Builder.ofType(MyMethodAnnotation.class)
.build();
new ByteBuddy()
.redefine(ClassThatNeedsToBeAnnotated.class)
.annotateType(description)
.method(ElementMatchers.anyOf(existingMethod))
// here I don't want to intercept method, I want to leave the method code untouched. How to do that?
.annotateMethod(annotationDescription)
.make()
.load(ClassThatNeedsToBeAnnotated.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
I'm sure that I just don't do it right but unfortunately cannot find an example when there is no code change for the method and only annotation change.
You found a blindspot in Byte Buddy that I thought of fixing for a while. Early versions of Byte Buddy did not allow for defining annotations but when it did, the API was already so widely used that I could not change it and it would require some bits in the implementation, too.
If you are willing to pay the minimal price of adding a synthetic method, you can rebase the class instead:
new ByteBuddy().rebase(ClassThatNeedsToBeAnnotated.class)
Doing so, you can just use the current API and add an implementation of SuperMethodCall. This will invoke the very same method in a rebasement.
This enhancement of Byte Buddy is tracked here: https://github.com/raphw/byte-buddy/issues/627
UPDATE: In the upcoming Byte Buddy 1.10.0 this is possible by:
new ByteBuddy()
.redefine(ClassThatNeedsToBeAnnotated.class)
.visit(new MemberAttributeExtension.ForMethod()
.annotateMethod(someAnnotation)
.on(matcher))
.make();
Annotation instance can be get by:
AnnotationDescription.Latent.Builder.ofType(AnnotationClass.class).build()
In my code have a method that is supposed to invoke the method doSomething of an object. Upfront, it is not known if the object's class does have the public method or not. Until now, I used the following code:
try {
Method method = component.getClass().getMethod("doSomething", Boolean.TYPE);
method.invoke(component, true);
} catch (final NoSuchMethodException e) {
// do nothing as for some components the method "doSomething" simply does not exist
}
I now wonder if I should try to avoid the NoSuchMethodExceptionby checking if the object's class does have the public method doSomething.
final Method method = Arrays.stream(component.getClass().getMethods())
.filter(m -> m.getName().equals("doSomething")).findFirst().orElse(null);
if (method != null) {
method.invoke(component, true);
}
What do you think is better?
The real question is if the refection is really necessary here.
learning cool tricks and knowing reflection is awesome and important for a developer, and it help you understand a lot about. but its not always the right solution .
maybe you should just have in interface something like .
public interface DoingSometing {
SomeReturnObject doSomething(Boolean param);
}
and the component should implement the interface, and in worst case scenario, you will have to do casting to avoid reflection and you might fly on ClassCastException if the object that you have in your possession
This might sound like a very easy question but I am really struggling to archive the solution.
Normally I mock and match quite easily my arguments.
Now I am matching a method that is like this:
getAppFacebookClient(page, V2_11).publish(destination, JsonObject.class, parameters.asArray());
this is for a facebook application and the parameters is a list of a custom Object. the asArray[] method was created in the class and basically does something like this:
public Parameter[] asArray() {
return parameters.toArray(new Parameter[parameters.size()]);
}
and the Parameter of this return is of the type com.restfb.Parameter
So, I am basically doing this
when(client.publish(anyString(), eq(JsonObject.class), any(com.restfb.Parameter[].class))).thenReturn(result);
but seems like it is never taken and of course I cannot manipulate result,
Any idea how could I mock this kind of objects in a proper way?
I also tried the other way
doReturn(result).when(client).publish(anyString(), eq(JsonObject.class), any(com.restfb.Parameter[].class));
Your code is correct ... unless the publish uses varargs!
In such a case you need to use any() / anyVararg() matcher.
Consider:
#Mock Thingy testee;
interface Thingy {
int f(String... arg);
}
#Test
public void test() {
// given
// works only if signature is `f(String[] arg)`
// when(this.testee.f(Mockito.any(String[].class))).thenReturn(42);
when(this.testee.f(Mockito.any())).thenReturn(42); // anyVararg() is deprecated
// when
final int result = this.testee.f(new String[] { "hello", "world" });
// then
assertThat(result, comparesEqualTo(42));
// works only if signature is `f(String[] arg)`
// verify(this.testee).f(Mockito.any(String[].class));
verify(this.testee).f(Mockito.any());
}
I have a few Management classes that are used for search methods, add, change and delete methods, print in table format method and write map to file method. The classes also have a container each as an attribute. Lets say there is a class X. This would be the class XManagement, and its container has objects of class X.
search() method returns the object of X, but first it gathers its ID via input.
add() method gathers input data for the creation of an object X, and the very last line of its code is for adding that object to its container.
change() method first searches for the object the user wants to change (via search() method), and then gathers data and changes the object via setter methods. It then calls the write() method for re-writing the file.
delete() method searches for the object (via search()), and then just removes it from its container, after which it calls the write() method.
The write() method is also void. It goes through the container for each object, and its data is then appended to a parse-able String, which is written to file.
Here are the examples:
public class XManagement {
protected Hashtable<Integer, X> xes = new Hashtable<>();
public XManagement(String fileName) {
// Constructor.
// Loads the input file, then parses it.
// Once parsed, the objects of X class are created.
// They are then put into the container (xes).
}
protected X search() {
// Both generic methods.
Integer uuid = enterInteger("ID");
return (X) find(uuid, xes);
}
public void add() {
Integer uuid = UUID(xes); // Generic method, generates UUID.hashCode()
// and checks for duplicates.
String a = enterString("Name");
Date d = enterDate("Start");
// ...............
X x = new X(uuid, a, d, etc);
xes.put(x.getID(), x);
write();
}
public void delete() {
X x = search();
xes.remove(x.getID(), x);
write();
}
public void change() {
X x = search();
String a = enterString("Name");
x.setA(a);
Date d = enterDate("Start");
x.setD(d);
// .......................
write();
}
protected void write() {
File file = new File("x.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(file));
String curr = "";
for (int id : xes.keySet()) {
curr += xes.get(id).getA() + "|" + xes.get(id).getD() + "|"; // etc
}
out.write(curr);
// There's, naturally, try/catch/finally here. For the sake of simplicity, I left it out here.
}
}
Class X goes like this:
public class X {
String a;
Date d;
// etc
public X(String a, Date d) {
this.a = a;
this.d = d;
}
// Getters and setters.
}
It's a lot more complicated than that, I just tried to keep it simple here to get some help - I'll try to figure out the harder stuff when I get the basics.
In some management classes, methods and constructors have the instances of other Management classes as their input parameters, so that they can call their methods inside, because most of them are connected. Let's say the Y class has X as an attribute, and when I create a Y object in YManagement add() method, I need to be able to choose one from all the available X objects from xes, via the search() method contained in XManagement.
I decided to keep it simple for now, but if you want, you can tell me how to approach testing where I'd have instances of other Management classes as an input.
How do I write detailed JUnit 5 test cases for these methods?
Sorry if I made a mistake somewhere in the code, I haven't copied it but written in here, generalizing the stuff that gets repeated in other Management classes.
If you have any other suggestions, as to the code itself, feel free to write that.
These methods are hard to test because they're doing too much. You have input, output to files, and data modifications.
Let's look at this method:
protected X search() {
// Both generic methods.
Integer uuid = enterInteger("ID");
return (X) find(uuid, xes);
}
Why do you call enterInteger when you could pass the desired ID into the method as a parameter? Let the client tell your class which ID to search for. Now the search is doing one thing: looking up a reference in the map.
I think that naming a class X gives no information whatsoever about what it's for. I'd prefer something that gives me a hint - better readability. You abstract all information out of the code with this naming scheme. Good names matter. Think harder about this one.
Your XManagement class looks like a simplistic in-memory database. Have you thought about using something that would allow you to use SQL? Maybe H2 would be a better choice. If this class were interface based you could swap out the implementation and clients would not have to change.
A better design would partition responsibility out to separate classes. For example, your data object could be accompanied by an interface-based persistence tier that would handle searches, updates, persistence, etc.
When I find that methods are too hard to test, it's usually a sign that the class needs to be redesigned. Hard to test is the same thing as hard to use for clients.
I'd replace your XManagement class with an interface:
package persistence;
public interface Repository<K, V> {
List<V> find();
V find(K id);
List<V> find(Predicate<V> filter);
void save(V v);
void update(V v);
void delete(K id);
void delete(V v);
}
You'll have an instance for each one of your Shows, Performances, Tickets, Users, etc.
package persistence;
public class ShowRepository implements Repository<Integer, Show> {
// TODO: You'll need a constructor and a Map for Shows.
public List<Show> find() { // the rest for you }
public Show find(Integer id) { // the rest for you }
public List<Show> find(Predicate<Show> filter) { // the rest for you }
public void save(Show v) { // the rest for you }
public void update(Show v) { // the rest for you }
public void delete(Integer id) { // the rest for you }
public void delete(Show v) { // the rest for you }
}
Much better than your X, in my opinion.
If you write your class using my interface there won't be any console interaction in those classes. Everything it needs is passed in by callers.
You can create separate concrete implementations for an in-memory cache, a relational or NoSQL database that each implement this interface.
You need to redesign your code as current implementation is untestable. I suggest following steps:
break your code to more cohesive classes;
extract interfaces;
use dependency injection for provided classes;
use parametrized methods;
After that you will be able to test your class with mocked dependencies or fake objects. Check out SOLID principles as if you follow them your code will be testable and maintanable.
You question is rather broad.
So, I will focus on the essential.
1) How to test void methods ?
A void method doesn't return any result but it creates side effect on the underlying object/system.
So you have to assert that the void method does what it is designed to do by asserting that the expected side effect is effective.
For example your add() method adds the object in the HashTable (you should rather use a HashMap or a ConcurrentHashMap if you have race conditions), so you should check that the object was correctly added.
You could for example have a search() method that return an object if it is contained. And by using it you could check if the object was added :
X x = ...;
xManagement.add(x);
X actualX = xManagement.search(x.getId());
assertEquals(x, actualX)
To do it, you have to make evolve your actual class that actually doesn't provide a simple retrieval method.
2) How to test classes that have dependencies with other classes ?
Unit tests of a class should be done in isolation of other classes.
So if YManagement methods have to invoke methods of XManagement, you should mock XManagement dependency and record a behavior for it.
Don't test twice the same thing.
If an object reference is passed to a method, is it possible to make the object "Read Only" to the method?
Not strictly speaking. That is, a reference that can mutate an object can not be turned into a reference that can not mutate an object. Also, there is not way to express that a type is immutable or mutable, other than using conventions.
The only feature that ensure some form of immutability would be final fields - once written they can not be modified.
That said, there are ways to design classes so that unwanted mutation are prevented. Here are some techniques:
Defensive Copying. Pass a copy of the object, so that if it is mutated it doesn't break your internal invariants.
Use access modifiers and/or interface to expose only read-only methods. You can use access modifieres (public/private/protected), possibly combined with interface, so that only certain methods are visible to the other object. If the methods that are exposed are read-only by nature, you are safe.
Make your object immutable by default. Any operation on the object returns actually a copy of the object.
Also, note that the API in the SDK have sometimes methods that return an immutable version of an object, e.g. Collections.unmodifiableList. An attempt to mutate an immutable list will throw an exception. This does not enforce immutability statically (at compile-time with the static type system), but is is a cheap and effective way to enforce it dynamically (at run-time).
There has been many research proposals of Java extension to better control of aliasing, and accessibility. For instance, addition of a readonly keyword. None of them is as far as I know planned for inclusion in future version of Java. You can have a look at these pointers if you're interested:
Why We Should Not Add ''Read-Only'' to Java (yet) -- it lists and compare most of the proposals
The Checker Framework: Custom pluggable types for Java -- a non intrusive way to extend the type system, notably with immutable types.
The Checker Framework is very interesting. In the Checker Framework, look at Generic Universe Types checker, IGJ immutability checker, and Javari immutability checker. The framework works using annotations, so it is not intrusive.
No, not without decorating, compositing, cloning, etc.
There's no general mechanism for that. You'll need to write special-case code to achieve it, like writing an immutable wrapper (see Collections.unmodifiableList).
You could achieve a similar thing in most cases by cloning the Object as the first statement of the method, such as this...
public void readOnlyMethod(Object test){
test = test.clone();
// other code here
}
So if you called readOnlyMethod() and pass in any Object, a clone of the Object will be taken. The clone uses the same name as the parameter of the method, so there's no risk of accidentally changing the original Object.
No. But you could try to clone the object before passing it, so any changes made by the method won't affect the original object.
making it implement a interface which has only read only methods (no setter methods) this gives a copy of an object (road-only copy) and returning the read only instance of interface instead of returning the instance of an object itself
You could define all parameters of the objects as final but that makes the object read only to everyone.
I believe your real question is about avoiding escape references.
As pointed out in some answers to extract an Interface from class and expose only get methods. It will prevent modification by accident but it is again not a foolproof solution to avoid above problem.
Consider below example:
Customer.java:
public class Customer implements CustomerReadOnly {
private String name;
private ArrayList<String> list;
public Customer(String name) {
this.name=name;
this.list = new ArrayList<>();
this.list.add("First");
this.list.add("Second");
}
#Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public ArrayList<String> getList() {
return list;
}
public void setList(ArrayList<String> list) {
this.list = list;
}
}
CustomerReadOnly.java:
public interface CustomerReadOnly {
String getName();
ArrayList<String> getList();
}
Main.java:
public class Test {
public static void main(String[] args) {
CustomerReadOnly c1 = new Customer("John");
System.out.println("printing list of class before modification");
for(String s : c1.getList()) {
System.out.println(s);
}
ArrayList<String> list = c1.getList();
list.set(0, "Not first");
System.out.println("printing list created here");
for(String s : list) {
System.out.println(s);
}
System.out.println("printing list of class after modification");
for(String s : c1.getList()) {
System.out.println(s);
}
}
}
Ouput:
printing list of class before modification
First
Second
printing list created here
Not first
Second
printing list of class after modification
Not first
Second
So, as you can see extracting interface and exposing only get methods works only if you don't have any mutable member variable.
If you have a collection as a member variable whose reference you don't want to get escape from class, you can use Collections.unmodifiableList() as pointed out in ewernli's answer.
With this no external code can modify the underlying collection and your data is fully read only.
But again when it comes to custom objects for doing the same, I am aware of the Interface method only as well which can prevent modification by accident but not sure about the foolproof way to avoid reference escape.
Depending on where you want the rule enforced. If you are working collaboratively on a project, use final with a comment telling the next person they are not meant to modify this value. Otherwise wouldn't you simply write the method to not touch the object?
public static void main(String[] args) {
cantTouchThis("Cant touch this");
}
/**
*
* #param value - break it down
*/
public static void cantTouchThis(final String value) {
System.out.println("Value: " + value);
value = "Nah nah nah nah"; //Compile time error
}
So specifically to this method, the value will never be written to, and it is enforced at compile time making the solution extremely robust. Outside the scope of this method, the object remains unaltered without having to create any sort of wrapper.
private boolean isExecuteWriteQueue = false;
public boolean isWriting(){
final boolean b = isExecuteWriteQueue;
return b;
}
Expanding on ewernli's answer...
If you own the classes, you can use read-only interfaces so that methods using a read-only reference of the object can only get read-only copies of the children; while the main class returns the writable versions.
example
public interface ReadOnlyA {
public ReadOnlyA getA();
}
public class A implements ReadOnlyA {
#Override
public A getA() {
return this;
}
public static void main(String[] cheese) {
ReadOnlyA test= new A();
ReadOnlyA b1 = test.getA();
A b2 = test.getA(); //compile error
}
}
If you don't own the classes, you could extend the class, overriding the setters to throw an error or no-op, and use separate setters. This would effectively make the base class reference the read-only one, however this can easily lead to confusion and hard to understand bugs, so make sure it is well documented.