how to destroy static objects? - issue when testing a static field - java

I would like to test this class and don't want to set id public or allow it to set it from outside.
public class A {
private int id;
private static int prevId = 0;
private static nextId(){
prevId++;
}
public A(){
id = nextId()
}
public int getId(){
return id;
}
...
}
if I test it and generate object of A in set up:
A foo;
#Before
public void setUp(){
foo = new A();
}
#Test
public void test1(){
assertEquals(1, foo.getId());
}
#Test
public void test2(){
assertEquals(1, foo.getId());
}
the test fails because setUp is called twice and therefore
the static field id is 2
assert fail not equals
expected 1
actual 2
As said above I don't want to have id with public access modifier,
otherwise I could set it to 0 by my own.
Is there a way to destroy the a static object in
the tear down method ?
#After
public void tearDown(){
//TODO finalize static object A
}

Quite simply - you can't, without providing some means to reset the prevId value. Decreased testability is one of the (many) arguments against mutable global state.
Instead of relying upon mutable global state like this, you can provide a factory class to create your A instances:
class AFactory {
private int nextId;
A createA() {
return new A(nextId++);
}
}
You will need to inject a single instance of AFactory wherever you currently need to create A instances. Now, in your test, you can simply create a new AFactory for each test case, and the nextId value will be start at zero each time.
Alternatively, you could invert control by creating some sort of unique value provider class:
final class UniqueValueProvider {
private int nextId;
int nextId() {
return nextId++;
}
}
and then make this a parameter of the constructor of A:
class A {
final int id;
A(UniqueValueProvider uvp) {
this.id = uvp.nextId();
}
}
which makes it more extensible if you want to arbitrarily subclass A:
class ChildOfA extends A {
ChildOfA(UniqueValueProvider uvp) {
super(uvp);
}
}
Again, in your tests you can simply create a new instance of UniqueValueProvider; you'd need to inject a single instance everywhere that you need to create an A (or one of its subclasses).
As a side note: you can also change the thing that you are testing. Instead of asserting that the ID is 1 each time, you can create two instances, and assert that the IDs are different/1 greater than the other etc:
Foo first = new Foo();
Foo second = new Foo();
assertNotEqual(first.getId(), second.getId());

If it is really just about the test scenario you described, just use reflection to reset value of the static member variable in your #Before method. If you are using Mockito, you can use their Whitebox helper to achieve this in a single line like so:
import org.mockito.internal.util.reflection.Whitebox;
Foo foo = new Foo();
#Before
public void setup() {
Whitebox.setInternalState(foo, "STATIC_MEMBER", 0);
}
#Test
public void staticMemberTest() {
assertEquals(0, foo.next());
assertEquals(1, foo.next());
}
#Test
public void anotherStaticMemberTest() {
assertEquals(0, foo.next());
assertEquals(1, foo.next());
}
private static class Foo {
private static int STATIC_MEMBER = 0;
public int next() {
return STATIC_MEMBER++;
}
}

Related

How do I test a void method sets the correct value for a private variable

public class ClassOne {
private String exampleString;
public String getExampleString(){
return this.exampleString;
}
public void setExampleString(String exampleString){
this.exampleString;
}
}
public class ClassOneTest {
ClassOne classOne = new ClassOne();
#Test
void getExampleStringTest(){
classOne.setExampleString("test");
assertEquals("test", classOne.getExampleString());
}
#Test
void setExampleStringTest(){
ClassOne classOneMock = mock(ClassOneMock.class);
ClassOneMock.setExampleString("test");
verify(classOneMock, times(1));
}
I have two methods, one which sets a variable and another which gets the value of that variable. I want to be able to test by mocking the set method and verifying that the value of the variable set is correct.
I tried using ArgumentCaptor, but I'm not sure if I understand it enough to use it.

Intercepting real non-static method calls with Mockito

Is there any way, using Mockito or PowerMockito, to intercept calls to non-static methods of an object, or at least of a singleton object?
An example is provided by the following classes:
public class Singleton {
private static Singleton INSTANCE = null;
private Singleton(Object parameter) {}
public static Singleton getInstance(Object parameter) {
if (INSTANCE == null) {
INSTANCE = new Singleton(parameter);
}
return INSTANCE;
}
public String process(String a, String b) {
return (a + b);
}
// Other methods
}
public class Foreign {
private Foreign() {}
public static void main(String[] args) {
System.out.println(Singleton.getInstance(new Object()).process("alpha", "beta"));
}
}
The Singleton object is created in a Foreign class, outside the control of some test code (not shown above). Neither of these two classes can be modified. The objective is to intercept calls to the non-static process() method in the test code so that, for certain values, a different result is returned, e.g. the call
Singleton.getInstance(new Object()).process("alpha", "beta");
mocked to return "alpha-beta" instead of the expected "alphabeta".
One solution could be intercepting the Singleton.getInstance() method to instantiate a custom subclass of the Singleton, e.g. using
public class SubSingleton extends Singleton {
public SubSingleton(Object parameter) {
super(parameter);
}
public String process(String a, String b) {
if ("alpha".equals(a) && "beta".equals(b)) {
return a + "-" + b;
}
return super.process(a + b);
}
}
Then, calls to the Singleton.process() method would be intercepted as in:
Object parameter = new Object();
PowerMockito.doReturn(new SubSingleton(parameter)).when(Singleton.class, "getInstance", parameter);
However, the Singleton class above only provides a private constructor, so it cannot be extended. Using PowerMockito.whenNew() to return a partial mock (spy) will also not work, since the Singleton class does not provide a no-args constructor.
Can the desired mocking be implemented in any other way? Can it be done for non-singleton classes?
Firstly, you can use whenNew for objects with constructor with some params:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {
#Mock
Singleton singletonMock;
#Before
public void setUp() throws Exception {
PowerMockito.whenNew(Singleton.class)
.withAnyArguments()
.thenReturn(singletonMock);
}
#Test
public void testMockNew() throws Exception {
Mockito.when(singletonMock.process(anyString(), anyString())).thenReturn("sasa");
Foreign.main(new String[0]);
}
}
Secondly, why not stub getInstance instead of new:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {
#Test
public void testMockNew() {
PowerMockito.mockStatic(Singleton.class);
Singleton singletonMock = Mockito.mock(Singleton.class);
PowerMockito.when(Singleton.getInstance(any())).thenReturn(singletonMock);
Mockito.when(singletonMock.process(anyString(), anyString())).thenReturn("sasa");
Foreign.main(new String[0]);
}
}
Thirdly, to intercept the process method:
create real singleton
create a mock singleton
mock static getInstance to return the mock. NOTE: you must call mockStatic after getting real instance.
use thenAnswer to check the arguments on process call
return desired answer if they match desired pattern
else call real method on real singleton
#RunWith(PowerMockRunner.class)
#PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {
#Test
public void testMockNew() {
var singletonReal = Singleton.getInstance(new Object());
var singletonMock = Mockito.mock(Singleton.class);
PowerMockito.mockStatic(Singleton.class);
PowerMockito.when(Singleton.getInstance(any())).thenReturn(singletonMock);
Mockito.when(singletonMock.process(anyString(), anyString())).thenAnswer((args) -> {
String a = args.getArgument(0);
String b = args.getArgument(1);
if ("alpha".equals(a) && "beta".equals(b)) {
return "sasa";
} else {
return singletonReal.process(a, b);
}
});
Foreign.main(new String[0]);
}
}
And finally, use a spy instead of a mock
#RunWith(PowerMockRunner.class)
#PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {
#Test
public void testMockNew() {
var singletonReal = Singleton.getInstance(new Object());
var singletonMock = Mockito.spy(singletonReal);
PowerMockito.mockStatic(Singleton.class);
PowerMockito.when(Singleton.getInstance(any())).thenReturn(singletonMock);
Mockito.when(singletonMock.process("alpha", "beta")).thenReturn("sasa");
// NOTE: real method is called for other args
Foreign.main(new String[0]);
}
}

How mock jcabi annotation parameters

I have some code like below.
#RetryOnFailure(attempts = Constant.RETRY_ATTEMPTS, delay = Constant.RETRY_DELAY, unit = TimeUnit.SECONDS)
public void method() {
// some processing
//throw exception if HTTP operation is not successful. (use of retry)
}
The value of RETRY_ATTEMPTS and RETRY_DELAY variable come from a separate Constant class, which are int primitive. Both the variable are defined as public static final.
How can I override these values while writing the unit testcases. The actual values increases running time of unit testcases.
I have already tried two approach: Both did not work
Using PowerMock with Whitebox.setInternalState().
Using Reflection as well.
Edit:
As mentioned by #yegor256, that it is not possible, I would like to know, why it is not possible? When these annotations get loaded?
There is no way to change them in runtime. What you should do, in order to make your method() testable is to create a separate "decorator" class:
interface Foo {
void method();
}
class FooWithRetry implements Foo {
private final Foo origin;
#Override
#RetryOnFailure(attempts = Constant.RETRY_ATTEMPTS)
public void method() {
this.origin.method();
}
}
Then, for test purposes, use another implementation of Foo:
class FooWithUnlimitedRetry implements Foo {
private final Foo origin;
#Override
#RetryOnFailure(attempts = 10000)
public void method() {
this.origin.method();
}
}
That's the best you can do. Unfortunately.

Making a static duplicate of non-static integer

For my programming class in first year engineering I have to make a D-game in Java, with only very little knowledge of Java.
In one class I am generating a random integer via
public int rbug = (int)(Math.random() * 18);
every so many ticks. I have to use this integer in another class (in the requirements for an if-loop), and apparently it needs to be static. But when I change the variable to public int static, the value doesn't change any more.
Is there an easy way to solve this problem?
Edit: part of code added:
public int rbug = (int)(Math.random() * 18);
which is used in
public void render(Graphics g){
g.drawImage(bugs.get(rbug), (int)x, (int)y, null);
And in another class:
if(Physics.Collision(this, game.eb, i, BadBug.rbug)){
}
As error for BadBug.rbug I get the message
Cannot make a static reference to a non-static field
Using static to make things easier to access is not a very good ideal for design. You would want to make variables have a "getter" to access them from another class' instance, and possibly even a "setter". An example of this:
public class Test {
String sample = 1337;
public Test(int value) {
this.sample = value;
}
public Test(){}
public int getSample() {
return this.sample;
}
public void setSample(int setter) {
this.sample = setter;
}
}
An example of how these are used:
Test example = new Test();
System.out.println(example.getSample()); // Prints: 1337
example = new Test(-1);
System.out.println(example.getSample()); // Prints: -1
example.setSample(12345);
System.out.println(example.getSample()); // Prints: 12345
Now you might be thinking "How do I get a string from the class that made the instance variable within the class?". That's simple as well, when you construct a class, you can pass a value of the class instance itself to the constructor of the class:
public class Project {
private TestTwo example;
public void onEnable() {
this.example = new TestTwo(this);
this.example.printFromProject();
}
public int getSample() {
return 1337;
}
}
public class TestTwo {
private final Project project;
public TestTwo(Project project) {
this.project = project;
}
public void printFromProject() {
System.out.println(this.project.getSample());
}
}
This allows you to keep single instances of classes by passing around your main class instance.
To answer the question about the "static accessor", that can also be done like this:
public class Test {
public static int someGlobal = /* default value */;
}
Which allows setting and getting values through Test.someGlobal. Note however that I would still say that this is a horrible practice.
Do you want to get a new number every time that you want BadBug.rbug? Then convert it from a variable to a method.

How to structure following requirements in JAVA classes

Scenario is like this:
There is a field in database 'overAllCount' which contains some value.
I have to use this variable in many classes I am designing.
I want to fetch this 'overAllCount' in one class say 'OverAllCountClass' and use it in all subclasses with its class name like OverAllCountClass.overAllCount. Basically like a static variable.
How can I do it?
My solution is:
public Class OverAllCountClass {
public static int OverAllCount;
public OverAllCountClass(){
// Fetch overAllCount from database here and set its value
}
}
////////// Use it like this //////////////
public class Usecount {
public void abc(){
// BUT IT IS NOT POSSIBLE becuase OverAllCountClass is not yet initialize
int mycount = OverAllCountClass.overAllCount
}
}
How can I achieve this?
If your concern is, the static variable overAllCount, might not get initialized and if you want it to get initialized whenever the class OverAllCountClass first gets invoked, then you can use Static initializer blocks
public class OverAllCountClass {
public static int overAllCount;
static {
overAllCount = fetchOverAllCount();
}
}
A static initializer block is invoked first time a class gets loaded. And a class gets first loaded when JVM sees that its been used.
public class Usecount {
public void abc(){
//When JVM sees that OberAllCountClass is used here, it executes the static block of OverAllCountClass and by the time below statement is executed, overAllCount is initialized
int mycount = OverAllCountClass.overAllCount
}
}
public Class OverAllCountClass {
protected int overAllCount; //will allow you to use in subclass too
public OverAllCountClass(){
// Fetch overAllCount from database here and set its value
}
public int getOverAllCount(){
return overAllCount;
}
}
public class Usecount {
//pass the instance of overAllCountInstance to UseCount somehow using constructor or setter
private OverAllCountClass overAllCountInstance;
public void abc(){
int mycount = overAllCountInstance.getOverAllCount();
}
}
No need to use static over here. Use getter to get the count
Rather than having a public static variable which can be modified/abused by other classes. I would provide a specific API which can hide the implementation and do things like lazy-loading if needed:
public static final Value getValue(){
//evaluate private field
return value;
}
This API can be a static method or be a singleton scoped method, depending on use case.
Another option is to make OverAllCountClass a Singleton.
public class OverAllCountClass {
private static final OverAllCountClass instance = new OverAllCountClass();
private Integer overAllCount = null;
// make it non-instanciable outside by making the constructor private
private OverAllCountClass {
}
public static OverAllCountClass getInstance() {
return instance;
}
public int getOverAllCount() {
if (overAllCount = null) {
//get value from database and assign it
}
return overAllCount;
}
}
This has the benefit that to code that accesses OverAllCountClass it is transparent wether it's a Singleton or not. This makes swapping out the implementation easier.

Categories

Resources