EasyMock capture: use getValue() outside of an IAnswer - java

Suppose I want to test a method Foo.doSomething(String arg):String using EasyMock. I know that I can use EasyMock Capture in order to capture the value set inside of the parameter and then get it at a later time. When writing my test, my goal is to capture the value when I mock out Foo's method and then get the value of the capture outside of my mocked method. I am trying something like this:
Capture<String> stringCapture = new Capture<String>();
EasyMock.expect(foo.doSomething(EasyMock.capture(stringCapture)).andAnswer(new IAnswer<String> {
#Override
public String answer() throws Throwable {
...
});
String retrievedValue = stringCapture.getValue();
However, I get a runtime error when I try to use getValue():
java.lang.AssertionError: Nothing captured yet
at org.easymock.Capture.getValue(Capture.java:80)
at com.example.Test.myTest(...)
....
I wish I could have a String variable within my test method but outside of the IAsnwer closure and set that variable's value inside of my IAnswer.answer() method. The problem is that the String variable must be marked as final in order to be accessible to the closure, which makes it unmodifiable and hence useless. Also, I do not wish to use a global just to solve this.
The only workaround I've thought of it to use my own class that has a String field, declare it as a final variable outside of IAnswer, set the captured value during answer() and finally set this value into a field within my test method. Perhaps there's a better way to do this because using another class to extract a captured value, or even a global variable, seems ugly to me.

The getValue will only work after the actual (replayed) call to foo. Before that, nothing is capture.
To set a variable inside answer(), because of Java requesting variables used in an inner class to be final, I normally use an AtomicReference. It's a nice placeholder for such things. The AtomicReference is then final but its content isn't.

Related

Java - should I use new() in Setters or not?

I see that a default setX function just uses X = _x, but in Java wouldn't it be just a reference to the _x object?
Shouldn't I use X = new X(_x) instead?
I truly looked for an answer, and haven't found one.
To be semantically correct, _x isn't an object, it's a parameter, and it's referring to an object. And yes, afterwards your X will be a copy of that reference, so it will point to the same object.
But usually that is exactly what you want to achieve. You don't want to spawn new objects whenever you set a value. And often you explicitly want it to be exactly the same object.
It's only if the calling site considers its version of the object as private property, that it's its responsability to produce and set a copy instead.
The name setter implies: setting a field.
That method isn't called storeCopyOf(), is it?
Of course you can use new (in case the corresponding class offers a copy constructor), but doing so in a setter is not common practice. And as shown, doing so is very misleading given the meaning that the name setX() communicates.
Shouldn't I use X = new X(_x) instead?
No, you shouldn't. A user of your API expects to set exactly the given instance, not a copy of it.
You could validate this incoming instance by throwing an exception if it doesn't fit your needs, but it's really unclear to set a copy.
Probably, you may want to return a value from a getter by using this approach. Returning a copy of an inner field (of a reference type) is a good technique to maintain immutability.
We use setter (and getter) method to implement encapsulation.
Example :
private String myField; //"private" means access to this is restricted
public String getMyField()
{
//include validation, logic, logging or whatever you like here
return this.myField;
}
public void setMyField(String value)
{
//include more logic
this.myField = value;
}
Someone who is using your APIs, will pass these value according to need, like :
obj.setMyField("myvalue");
If x is a primitive type, then there is no need to recreate the value with a copy constructor as changes to its value elsewhere won't affect the local copy.
If you are setting a mutable (changeable) object, but you don't want your copy changed, then yes you should use a copy constructor in your setter. However I'd hesitate to call that setting, it's more like a saveCopy(_x);

How to grab a return value from a sub-method

I am required to take all user input from within a void method (though it's important to note that the original verbiage says the method must not have a return value), and have all output be relegated to a separate method.
Now, I have all that set up and it's passing the relevant array to the sub method just fine (because I call the sub method from within the void method). But, I need the main to actually do the rest of the calling using the value from that sub method in other methods.
An in depth explanation and teaching would be deeply appreciated.
If you have luxury to change the signature of the methods (keeping the return type as void), you can pass another data structure to the methods. That way, you can get the user inputs inside GetUserInput(customDataStruct) method, pass it to SubMethod(customDataStruct) method. SubMethod() will modify the customDataStruct content, which will be available directly in main(), if main() invokes GetuserInput().
Second option, as #Fiddle suggested, is to use a global variable and let the methods manipulate it. This global variable shall be accessible from main().
I had it flipped. By letting the void method be the sub method and actually learning to pass by reference (enjoy my head smacking) I was able to use the method with the return to bring the value back to main.

Local variable log defined in an enclosing scope must be final or effectively final

I'm new to lambda and Java8. I'm facing following error.
Local variable log defined in an enclosing scope must be final or
effectively final
public JavaRDD<String> modify(JavaRDD<String> filteredRdd) {
filteredRdd.map(log -> {
placeHolder.forEach(text -> {
//error comes here
log = log.replace(text, ",");
});
return log;
});
return null;
}
The message says exactly what the problem is: your variable log must be final (that is: carry the keyword final) or be effectively final (that is: you only assign a value to it once outside of the lambda). Otherwise, you can't use that variable within your lambda statement.
But of course, that conflicts with your usage of log. The point is: you can't write to something external from within the lambda ... so you have to step back and look for other ways for whatever you intend to do.
In that sense: just believe the compiler.
Beyond that, there is one core point to understand: you can not use a local variable that you can write to. Local variables are "copied" into the context of the lambda at runtime, and in order to achieve deterministic behavior, they can only be read, and should be constants.
If your use case is to write to some object, then it should be a field of your enclosing class for example!
So, long story short:
local variables used (read) inside a lambda must act like a constant
you can not write to local variables!
or the other way round: if you need something to write to, you have to use a field of your surrounding class for example (or provide a call back method)
The reason for this limitation is the same as the reason for the Java language feature that local variables accessed from within (anonymous) inner classes must be (effectively) final.
This answer by rgettman gets into the details of it. rgettman explains the limitations in clear detail and I link to that answer because the behavior of lambda expressions should be same as that of anonymous inner classes. Note that such limitation does not exist for class or instance variables, however. The main reason for this is slightly complicated and I couldn't explain it better than what Roedy Green does it here. Copying here only so it is at one place:
The rule is anonymous inner classes may only access final local
variables of the enclosing method. Why? Because the inner class’s
methods may be invoked later, long after the method that spawned it
has terminated, e.g. by an AWT (Advanced Windowing Toolkit) event. The
local variables are long gone. The anonymous class then must work with
flash frozen copies of just the ones it needs squirreled away covertly
by the compiler in the anonymous inner class object. You might ask,
why do the local variables have to be final? Could not the compiler
just as well take a copy of non-final local variables, much the way it
does for a non-final parameters? If it did so, you would have two
copies of the variable. Each could change independently, much like
caller and callee’s copy of a parameter, however you would use the
same syntax to access either copy. This would be confusing. So Sun
insisted the local be final. This makes irrelevant that there are
actually two copies of it.
The ability for an anonymous class to access the caller’s final local
variables is really just syntactic sugar for automatically passing in
some local variables as extra constructor parameters. The whole thing
smells to me of diluted eau de kludge.
Remember method inner classes can`t modify any value from their surrounding method. Your second lambda expression in forecach is trying to access its surrounding method variable (log).
To solve this you can avoid using lambda in for each and so a simple for each and re-palace all the values in log.
filteredRdd.map(log -> {
for (String text:placeHolder){
log = log.replace(text,",");
}
return log;
});
In some use cases there can be a work around. The following code complains about the startTime variable not being effectively final:
List<Report> reportsBeforeTime = reports.stream()
.filter(r->r.getTime().isAfter(startTime))
.collect(Collectors.toList());
So, just copy the value to a final variable before passing it to lambda:
final LocalTime finalStartTime = startTime;
List<Report> reportsBeforeTime = reports.stream()
.filter(r->r.getTime().isAfter(finalStartTime))
.collect(Collectors.toList());
However, If you need to change a local variable inside a lambda function, that won't work.
If you do not want to create your own object wrapper, you can use AtomicReference, for example:
AtomicReference<String> data = new AtomicReference<>();
Test.lamdaTest(()-> {
//data = ans.get(); <--- can't do this, so we do as below
data.set("to change local variable");
});
return data.get();
One solution is to encapsulate the code in an enclosing (inner class). You can define this:
public abstract class ValueContext<T> {
public T value;
public abstract void run();
}
And then use it like this (example of a String value):
final ValueContext<String> context = new ValueContext<String>(myString) {
#Override
public void run() {
// Your code here; lambda or other enclosing classes that want to work on myString,
// but use 'value' instead of 'myString'
value = doSomethingWithMyString(value);
}};
context.run();
myString = context.value;

Calling instance method in Java

Following this tutorial:
http://developer.android.com/training/notepad/notepad-ex2.html
In Step 2, this method gets called:
registerForContextMenu(getListView());
which is a public method of Activity. Now, I'm a bit of a Java newbie here - I thought if you wanted to call an instance method of a superclass you needed to preface it with this. E.g.
this.registerForContextMenu(getListView());
Is it just a style thing here? Is there any difference between
this.registerForContextMenu
and simply
registerForContextMenu
No, there is no difference.
You don't have to use this., but it is often done anyway to make the code clearer.
For one thing, it makes it easy to tell if a method is static or not if you use the convention of calling instance methods like this:
this.registerForContextMenu() 
and static methods like this:
ClassName.staticRegisterForContextMenu()
you do not have to use this. If you ommit it it is assumed you called method in this scope. One particular example when this may help could be i.e.:
Boolean someVar;
public function setMe( Boolean someVar ) {
this.someVar = someVar;
}
In this case, w/o this you would get the error.
To call a method of superclass either you need object of superclss or keyword super .
eg.
superObject.superclassMethod();
super.superclassMethod();
this is a reference of the current object. this can be used to call method of a class in which it is used. this can never be used to call a superclass method.
As for
this.registerForContextMenu()
and
registerForContextMenu()
no such difference. you can use either of them.
Both ways are correct for calling a method on the current (this) instance of the class. Non private methods are inherited from super classes, so you can use the same syntax to call such methods.

Would this work - Public Class

I would like to know if the following code should work:
if (M != 0){
Tools.Printer(stdnr);
}
Background Info:
I created a public class Tools with a few functions. One of the functions is the void Printer function. Is there a rule or something that if you want to use Tools.something you need to do assign the Tools.something to an integer / print it, etc. Or is Tools.Printer supposed to work on its own.
I ask this because I can't find anything wrong with my code. I would be glad if someone can help me right with the terms I used above - I suppose they are terribly wrong...
Thank a lot, Help would be greatly appreciated
If your method is a void type, it returns nothing, therefore you do not need to assign it to a variable (in fact, you'll get a compile time error if you do).
If it was instead a function, like it returned some value, for instance:
public String foo()
{
return "kdfldj";
}
You still don't necessary need to assign it to a variable. The returned value will just be discarded. For example, StringBuilder.append returns back the StringBuilder that you just appended to, but you can safely call it like this:
myStringBuilder.append("some text");
And ignore the return value.
However, if your Tools.Printer method is not a static method, you do need to create an instance of Tools, either assigned to a variable like this:
Tools tools = new Tools();
tools.Printer(stdnr);
or initialized without being placed in a variable:
new Tools().Printer(stdnr);
But if Printer is a static method, your code should be fine, since you are calling the method by the class it's contained in.

Categories