Programming Language : Java
Testing tool : powermockito,Junit
I have a static block in my code. I am using that code particle as several reference. While during integration testing (using powermockito) I mocked a getWebDetails() method in the below example. The method for mocking (getWebDetails) is also getting called from the static block in my program, so it excecutes before my test gets excecuted and returns a null value. I need to assign values to xml contents during my testing.
class test1{
private static String xmlcontents;
static {
xmlcontents= ServiceUtils.getWebDetails();
}
public static String getWebDetails() throws Exception{
url = test2.getURL();
return url;
}
}
Nota bene (please note): I tried using #SuppressStaticInitializationFor("test1"), but it suppresses all the static methods inside the class.
Can anyone help me? Any help will be highly appreciable..
Related
I've included my code below. Following some other examples, I even tried to dynamically load the class in order to force it to run the static block, but that doesn't solve my problem. The class is loaded and class.getName() is printed successfully, but still, when it gets to the last line in the main method it throws an error saying the array is null.
All the other answers address things which don't seem to apply here, like how using the "final" keyword can allow the compiler to skip static blocks. Any help is appreciated!
package helper;
public class StaticTest {
public static boolean [] ALL_TRUE;
private static void setArray(){
ALL_TRUE = new boolean[8];
for(int i=0;i<ALL_TRUE.length;i++){
ALL_TRUE[i] = true;
}
}
static {
setArray();
}
public static void main(String [] args){
ClassLoader cLoader = StaticTest.class.getClassLoader();
try{
Class aClass = cLoader.loadClass("helper.StaticTest");
System.out.println("aClass.getName() = " + aClass.getName());
} catch(ClassNotFoundException e){
e.printStackTrace(System.out);
}
System.out.println(StaticTest.ALL_TRUE[0]);
}
}
In case anyone else lands here, the problem was that I had checked the Netbeans option "Compile on Save" (under Build->Compiling). Somehow, compiling files immediately upon saving was preventing the static block from being run.
Again, thanks to everyone who chimed in to verify that the code itself worked as expected.
I am currently trying to call Java Code in C#. One possibility is IKVM, whereupon I looked at a tutorial for this tool. I have to say, and that's really curious: the tool seems to work in part.
But now to my problem:
So I took the following tutorial (https://www.codeproject.com/Articles/594632/IKVM-NET-in-Details). Following this example, I wrote my own Java code. In addition, I have added a few more methods to the java file. My source code for testing is relatively short:
The Java source code:
package TestProject;
public class TestClassJava {
public static void Print() {
System.out.println("Hi C# from JAVA");
}
public static void PrintStr(String str) {
System.out.println(str);
}
public static String returnString() {
return "Hi C# from Java method";
}
public static String returnInputString(String input) {
return input;
}
public static int retInt() {
return 42;
}
public static int returnIntNumber(int inp) {
return inp;
}
public static boolean returnTrueBoolean() {
return true;
}
}
The C# source code:
using System;
using System.IO;
using TestProject;
using ikvm.io;
using ikvm.lang;
using ikvm;
using ikvm.runtime;
using ikvm.extensions;
namespace IKVM_Test_Case_08_08_2019
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(TestClassJava.retInt()); // shows: 42 (works!)
Console.WriteLine(TestClassJava.returnString()); // shows: Hi C# from Java method (works!)
TestClassJava.Print(); // here appears the error System.TypeInitializationException
TestClassJava.PrintStr("Hallo"); // here appears the error System.TypeInitializationException
Console.WriteLine(TestClassJava.Print()); // can not convert from void to bool
}
}
}
The whimsical part now happens while running the program in C#. I try the methods in C# via Console.WriteLine(TestClassJava.retInt()); then, for example, the number 42 will be given to me, as it should be. I can also call the method returnString().
In the methods without return value, however, Print() & PrintStr(String str), I always get the following error message:
Error message:
System.TypeInitializationException
HResult=0x80131534
Message=The type initializer for 'java.lang.StdIO' threw an exception.
Source=IKVM.OpenJDK.Core
StackTrace:
at java.lang.System.get_out()
at TestProject.TestClassJava.Print()
at IKVM_Test_Case_08_08_2019.Program.Main(String[] args) in C:\Users\...\source\repos\IKVM_Test_Case_08_08_2019\IKVM_Test_Case_08_08_2019\Program.cs:line 19
Inner Exception 1:
MissingMethodException: Method not found: 'Void System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.Security.AccessControl.FileSystemRights, System.IO.FileShare, Int32, System.IO.FileOptions)'.
I can not quite explain that, so I asked this question in the hope, that someone knows an advice.
According to the quoted tutorial, it all had to work that way. Nevertheless, I get this error message.
I hope my question is so far understandable.
I Have three classes
StaticHolder.java - Which holds a static variable.
StaticInitializer.java -Responsible only for initializing the variable through a static method.
Application.java - Retrieves the static variables value through getter method.
I thought initializing a static variable once in JVM will not go until we stop the JVM. So I called ran StaticInitializer once which will do the initialization. And tired to access its value from another class which is not working and returning null. Can anyone explain why. Thanks In Advance.
public class StaticHolder {
private static String hello;
public static void ini() {
hello = "Hello World";
}
public static String getHello() {
return hello;
}
public static void setHello(String hello) {
StaticHolder.hello = hello;
}
}
class StaticInitializer {
public static void main(String[] args) {
StaticHolder.ini();
while (true) {
Thread.sleep(1000);
}
}
}
public class Application {
public static void main(String[] args) {
System.out.println(StaticHolder.getHello());
}
}
static does not mean that this value is there forever!
It is only theree for the current java session.
Invocing the java command at the command line starts a new java session where the value needs to be initialized again.
Actually I have a daemon thread which does the initialization and stays alive.And I have another stand alone java program which tries to get the value.
Without knowing that other code involved my gueass is that you did not establish inter process communication.
The easiest way it that you "deamon" opens a server socket and your "stand alone java program" connects to it an queries the desired data through it.
So there is only one main method that can be executed as entry point for the entire application for each JVM run.
When the JVM is executed you can specify which class has to be loaded at start. The Classloader take care to load that class and then the JVM can execute the only one public static void main(String[] args) method.
In Java you need to have at least one class with a public static method named main. I suggest to read this post to understand why it is public static.
The Java Classloader is a part of the Java Runtime Environment that
dynamically loads Java classes into the Java Virtual Machine.
Usually classes are only loaded on demand.
So returning to your question, given that when Application.main is running there is no way to execute StaticHolder.init(), I suggest to change your main in this way:
public class Application {
public static void main(String[] args) {
StaticHolder.init();
System.out.println(StaticHolder.getHello());
}
}
or change StaticHolder in this way and remove the init:
public class StaticHolder {
private static String hello;
static {
hello = "Hello World";
}
public static String getHello() {
return hello;
}
public static void setHello(String hello) {
StaticHolder.hello = hello;
}
}
On the other hand, just to be clear if you run the StaticInitializer.main this has no effect on Application.main execution.
In your program , when main method of StaticInitializer is first executed, a String named hello is initalized. and as ini() method is called, the value 'Hello world' is assigned to hello. Then jvm exists main method, and then stops working. Again when we compile application class,instead of the previous hello variable , a new hello string variable is created with no value assigned(null valued) . That's why you're getting null as output. Thankyou.
I have a class which writes messages to some logs. The class is a utility which doesn't do anything else, it runs in the background, checks a few things and logs them. I'm wondering if it's possible for me to verify in a unit test that the log has been written to without caring about what it is actually writing. Here's my class being tested:
//imports...
public class MyClass {
private static Log log = LogFactory.getLog(MyClass.class);
public MyClass() {
log.info("MyClass is being created.");
}
public void doThing() {
if( everything_is_fine ) {
log.info("This is a message to say everything is fine.");
} else {
log.error("Uh oh...");
}
}
}
And my tester class:
// imports ...
#RunWith(PowerMockRunner.class)
#PrepareForTest({MyClass.class,LogFactory.class})
public class MyClassTest {
Log mockLog;
#Before
public void setup() {
PowerMockito.mockStatic(LogFactory.class);
mockLog = mock(Log.class);
PowerMockito.when(LogFactory.getLog(MyClass.class)).thenReturn(mockLog);
}
#Test
public void test_everything_is_ok() {
MyClass mything = new MyClass(); // should write to log.info
mything.doThing(); // should write to log.info
verify(mockLog, atLeastOnce()).info(anyString());
verify(mockLog, never()).error(anyString());
}
#Test
public void test_everything_is_not_ok() {
MyClass mything = new MyClass(); // should write to log.info
// do something which makes things not ok
mything.doThing(); // should write to log.error
verify(mockLog, atLeastOnce()).info(anyString());
verify(mockLog, atLeastOnce()).error(anyString());
}
}
When I run the tests, I expect that the log.info() is invoked for both tests, and the log.error() is invoked only for the second. However I'm getting a "Wanted but not invoked" for the log.info for both tests. and for log.error on the second. So either:
1) My code is broken and not writing to the log, or
2) My test is broken.
I'm thinking that I've messed up something in my test, probably something really obvious, so has anyone had experience testing something like this who could help me out? Any and all help will be appreciated.
UPDATE:
Thanks to those who helped out, I've got a solution now.
After playing around with the code for a bit, I discovered that there seems to be an issue with the initialization of the log. Doing private static Log log = LogFactory.getLog(MyClass.class); didn't seem to use the mock correctly, so if I move it to the constructor it seemed to be mocked OK and my tests all work as expected:
public class MyClass {
private static Log log;
public MyClass() {
MyClass.log = LogFactory.getLog(MyClass.class);
log.info("MyClass is being created.");
}
// etc ...
}
I've got it working now, but can anyone explain why initializing the log the first way didn't work? Or perhaps point me to somewhere which explains it? I'm not sure if there's a gap in my understanding of how Java initializes objects or if it's a limitation of mocking frameworks.
You can make an abstraction over the Logger like we did here in our project:
https://github.com/4finance/uptodate-gradle-plugin/blob/master/src/main/groovy/com/ofg/uptodate/LoggerProxy.groovy
Then you have to constructors
https://github.com/4finance/uptodate-gradle-plugin/blob/master/src/main/groovy/com/ofg/uptodate/UptodatePlugin.groovy
One with LoggerProxy initialized and one for tests where you can mock it out and verify if proper text was passed. No need for dirty hacks ;)
Since I had the same problem (private static Log log = LogFactory.getLog(MyClass.class);), I'm posting what I did to solve it.
Instead of modifying logger initialization (I was limited by coding rules) I simply split test in different classes...
I am not even sure if this is possible, but I came up with this idea because of this question: Change private static final field using Java reflection
So this is the scenario:
public static String test() {
return "test test test";
}
What I want to do this let the test() method return "worked" instead of "test test test".
Does anybody have an idea how to accomplish this?
EDIT:
I downloaded powermock and tried this:
package test;
import org.powermock.api.easymock.PowerMock;
public class InjectorTest {
public static void main(final String[] args) {
System.out.println("Before the injection:");
System.out.println(test());
PowerMock.mockStatic(InjectorTest.class);
PowerMock.doReturn("worked").when(InjectorTest.class, "test");
System.out.println("After the injection:");
System.out.println(test());
}
public static String test() {
return "did not work :(";
}
}
But eclipse gives this error: The method doReturn(String) is undefined for the type PowerMock
Did I download the wrong one or was that a bad sample code?
Because I don't want more votedowns, WHY I want to do this?
I want to inject Minecraft in that way that it doesn't uses the user.home but a relative URI.
In this way I can make a pre-installed portable Minecraft for an USB stick for school :D
I think PowerMock can do this. (Java reflection under the hood)
With PowerMock, your code would look like this:
public static void main(String[] args) {
PowerMock.mockStatic(Foo.class);
PowerMock.doReturn("worked").when(Foo.class, "test");
System.out.println(Foo.test());
}
Credits to #RC for code above