I have a helper class with some static final strings as follows
public static final String abc = "abc"
In my test though, I want to use the value
public static final String abc = "xyz"
So I added the following
private static final HelperClass mock = mock(HelperClass.class);
#Before
when(mock.abc).thenReturn("xyz")
The actual code to test
public void codeToTest() {
// use Helperclass.abc
// other logic
But this declaration is not allowed since it needs to be a method invocation. (MissingMethodInvocation) How do I use the static variables in the test?
Static values can make some tests a bit more difficult. You won't be able to use mocking to get this value. But I have to ask why you would want to mock this. It isn't testing anything in the helper class to access this variable and you are wanting a constant, why not just define and use the constant in your test?
Create Another Mocked class as below.
private static class MockedHelperClass extends MockUp<HelperClass>
{
public static final String abc = "xyz"
#Mock
String getABC()
{
return abc;
}
}
Then use this mocked class as below in Test Method
MockedHelperClass helperClass = new MockedHelperClass();
helperClass.abc = "xyz";
helperClass.getABC();
You should re-think your design, changing static variables in tests isn't a good practice. However, if you really want to to that, you can use reflection.
static void setStatic(Field field, Object value) throws Exception {
field.setAccessible(true);
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, value);
}
Invocation example:
setStatic(MyClass.class.getField("abc"), "xyz");
Related
In Java, I have a class like for example
public class A {
private final Map<Integer, String> steps = ImmutableMap.of(
1, "one"
);
public String getStepOne() {
return steps.get(1);
}
}
Now I need to somehow mock this global variable in a unit test. Unfortunately, I was told to avoid any changes in source code of the tested class for testing purposes, especially, simply providing a getter wouldn't be a satisfying solution.
My attempt was to mock the static method call like
#RunWith(PowerMockRunner.class)
#PrepareForTest({A.class, ImmutableMap.class})
public class ATest {
private A subj = new A();
#Before
public void setUp() {
PowerMockito.mockStatic(ImmutableMap.class);
ImmutableMap<Object, Object> mockedMap = ImmutableMap.of(1, "NEW ONE");
BDDMockito.given(ImmutableMap.of()).willReturn(mockedMap);
}
#Test
public void testGetStepOne() {
System.out.println(subj.getStepOne());
}
}
But this doesn't work, it prints "one" and not "NEW ONE". I suspect that mocking static method calls this way isn't possible if they are called from the initialization of a global variable ... does somebody know if there is any way to mock this variable (as I said, without changes in class A)?
============ EDIT ==================
Well, I agree that generally it does not make much sense to mock an immutable map, but actually, the map looks more like this:
private final Map<Integer, B> steps = ImmutableMap.of(
1, new B()
);
and what I actually need, is to mock the object of type B, which is one of the values, because it is accessed in further methods of the class via steps.get(...).
A pure Java solution might be to use reflection in the #Before method. The trick is to get rid of the final property at first, and then to change the value. See the 1st answer of this: Change private static final field using Java reflection. Same should work for non static members.
See the modified code from this post here: Java reflection example to change final member
I have below code, where I have a final inner class.
So as per final it should not allow to re-assign it a value. But it still does. Please explain:
public class POJO {
public final String vNew;
public POJO () {
vNew="hello";
}
final class abc {
String name="abc";
}
public static void main(String[] args) {
POJO vPOJO = new POJO();
POJO.abc in=vPOJO.new abc();
System.out.println(in.name);
in.name="World";
System.out.println(in.name);
in=vPOJO.new abc();
System.out.println(in.name);
}
}
Output is
abc
World
abc
The code POJO.abc in=vPOJO.new abc(); and in=vPOJO.new abc(); is re-assignment isn't it.
Just not sure as it uses the handle of outer non final class, makes it work.
If a class is final, it just means it can't be extended.
If you want to prevent reassignment, make the variable final.
POJO vPOJO = new POJO();
final POJO.abc in = vPOJO.new abc(); //Notice the final
System.out.println(in.name);
in.name = "World";
System.out.println(in.name);
in = vPOJO.new abc(); // Compilation error
System.out.println(in.name);
And of course, if you want to prevent reassignment of the name field, make the field final instead. If you did that,
in.name = "World";
would no longer compile.
This Wikipedia article describes various uses of final. Summed up, they are:
final classes
can't be extended
final methods
can't be overridden
final variables/fields
can't be reassigned
There is also the issue of static final methods.
The class is final:
final class abc {
String name="abc";
}
but not the field. And of course that is the same as with "normal" classes - it prevents subclassing that inner class. That is all there is to this!
To prevent re-assining that value; you do what you do for normal classes as well:
class abc {
final String name="abc";
}
make the field final!
See here for further reading what final is about, depending on the context.
What's wrong with below enum declaration? I want to write a singleton enum, so declared INSTANCE.
I get errors - "misplaced construct(s)"
public enum demo {
INSTANCE;
WHITE(21), BLACK(22), RED(23), YELLOW(24), BLUE(25);
private int code;
private demo(int c) {
code = c;
}
private demo() { }
public int getCode() {
return code;
}
}
In order to get it compiling, just replace the ; with ,, as you haven't finished listing the constants.
Something like this:
INSTANCE,
WHITE(21), BLACK(22), RED(23), YELLOW(24), BLUE(25);
However, since you want to have a singleton, I suggest to get rid of the INSTANCE value, and introduce a static member that will hold the instance:
public static Demo INSTANCE = Demo.WHITE;
You cannot declare two sets of instances within one enum class as you've done.
It isn't clear why you want an enum singleton of an enum, but if you want one INSTANCE to be a singleton, then you can declare a static variable to be one of the instances.
enum Demo {
WHITE(21), BLACK(22), RED(23), YELLOW(24), BLUE(25);
public static Demo INSTANCE = WHITE;
// rest unchanged except for demo->Demo
}
It's possible to use the enum singleton pattern:
enum DemoSingleton
{
INSTANCE(Demo.WHITE);
private Demo myDemo;
private DemoSingleton(Demo demo) { myDemo = demo; }
}
But that would be useless; you could just use Demo.WHITE.
In Java we can do the following to initialize class and call method inside that class:
public class MyClass {
public String myClassMethod() {
return "MyClass";
}
}
.
public class Test {
public static void main(String[] args) {
MyClass myClass = new MyClass(); // initialize MyClass
myClass.myClassMethod();// call a method
}
}
If my class is an enum class, implementation will be the following:
public enum MyEnumClass {
INSTANCE;
public String myEnumClassMethod() {
return "MyEnumClass";
}
}
.
public class Test {
public static void main(String[] args) {
MyEnumClass myEnumClass = MyEnumClass.INSTANCE;
myEnumClass.myEnumClassMethod();
}
}
Both of these cases works in the same way, but it is said to be better in the enum implementation. My question is why and how it is happening?
An enum is essentially a singleton pattern.
The JVM handles the initialization and storage of enum instances. To see this most clearly you can write:
public enum MyEnumClass {
INSTANCE("some value for the string.");
private final String someString;
private MyEnumClass(final String someString) {
this.someString = someString;
}
public String getSomeString(){
return someString;
}
}
And in another class:
public static void main(String[] args) {
final MyEnumClass myEnumClass = MyEnumClass.INSTANCE;
system.out.println(myEnumClass.getSomeString());
}
This would print out "some value for the string.".
This demonstrates that the enum instances are initialised at class load time, i.e. as if by the static initialiser.
Or put another way:
new MyClass() == new MyClass();
Is always false, whereas:
MyEnumClass.INSTANCE == MyEnumClass.INSTANCE;
Is always true. i.e. MyEnumClass.INSTANCE is always the same MyEnumClass.INSTANCE whereas a new MyClass is created every time your call new MyClass().
This brings us nicely to your question of "better".
An enum is a singleton instance with various nifty methods for converting String enum names into a reference to the singleton instance that it represents. It also guarantees that if you de-serialize an enum there won't be two separate instances like there would for a normal class.
So an enum is certainly much better as a robust and threadsafe singleton than a class.
But we cannot have two instances of INSTANCE with the different values for someString so the enum is useless as a class...
In short enums are good for what they're good for and classes are good for what they're good for. They are not substitutes and therefore cannot be compared in any meaningful way expect when one is used as the other.
It's a simple implementation of the Singleton pattern, relying on the mechanisms of how Enum's work.
If you use MyEnumClass.INSTANCE a second time, you'll get the same object instance.
In contrast, new MyClass(); will create a new object.
See also discussion here:
What is the best approach for using an Enum as a singleton in Java?
There would possibly be more to learn by reading Java Language Spec Section 8-9
A very simple question for the experts, but for a beginner like me, it is just confusing. I thought I understood Static, but apparently I do not. This below is the entire class, and it says I need to make test static. But I don't want to. What can I do to fix this, and why is it happening in the first place? Thanks!
public class SubstringTest
{
private String test;
public static void main(String[] args)
{
test = "Penguin";
System.out.println(test);
System.out.println(test.substring(3));
}
}
main is static. test is not.
If you don't want to make test static, you have to create an instance of SubstringTest first.
SubstringTest st = new SubstringTest(); // create an instance
st.test = "test"; // this works
System.out.println(st.test); // also works
If test is static, you can do
SubstringTest.test = "test";
Or if the code you're writing is in the class SubstringTest and test is static:
test = "test";
A static method cannot access non-static/instance variables, because a static method is never associated with any instance. A static method can’t directly invoke a non-static variable. But static method can access non-static variable by means of declaring instances and using them.
public class SubstringTest
{
private String test; // make it private static String test;
public static void main(String[] args)
{ // SubstringTest t = new SubstringTest(); Or change here.
// t.test ="Penguin";
test = "Penguin";
System.out.println(test);
System.out.println(test.substring(3));
}
}
You CANNOT access instance variables from a Static method.
Because a static method is called on a class instance and not to an object of a class. This means, that a static method is not able to access instance variables, because they are only instantiated in an object