I am using powermock and meet two problems like this:
public LogUtils {
public static enum Type {
****
}
public void log(Type type, Date date) {
***
}
}
public class Service {
public int call() {
LogUtils.log(Type.T1, new Date());
***
return *;
}
}
#RunWith(PowerMockRunner.class)
public class TestService {
#Test
#PrepareForTest(LogUtils.class)
public void test() {
Service service = new Service();
PowerMockito.mockStatic(LogUtils.class);
LogUtils.log(Type.T1, new Date()); // test here, but failed.
service.
}
#Test
#PrepareForTest(LogUtils.class)
public void test2() {
Service service = new Service();
PowerMockito.mockStatic(LogUtils.class);
LogUtils.log(Type.T1, new Date());
int ret = service.call();
Assert.isTrue(1, ret);
}
}
For test1, it would throw Exception:
java.lang.VerifyError: Bad type on operand stack in arraylength
Exception Details:
Location:
LogUtilss$Type.values()[LogUtils$Type; #137: arraylength
Reason:
Invalid type: 'java/lang/Object' (current frame, stack[2])
Current Frame:
bci: #137
flags: { }
locals: { 'java/lang/Object', top, top, top, 'java/lang/Object' }
stack: { 'java/lang/Object', integer, 'java/lang/Object' }
it is caused by defining static enum in class instead of directly creating enum with single file. How to solve this problem as our codes almost define static enum in class?
For test2, if the first problem is solved, the direct call of LogUtils.log could be successfully skipped, but when call service.call(), couldn't skip.
Anyone could kindly help on this? Thanks a lot in advance.
I use powermock 1.6.5 and JDK1.7
Full code example:
public class LogUtils {
public static enum Type {
T(1),
D(2);
private int type;
Type(int type) {
type = type;
}
}
public static void log(Type t, String msg) {
System.out.println("skip this method");
}
}
public class TestAction {
public void test() {
String msg = "logMsg";
LogUtils.log(LogUtils.Type.T, msg);
}
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
public class UnitTest {
#Test
#PrepareForTest(LogUtils.class)
public void test() {
PowerMockito.mockStatic(LogUtils.class);
TestAction a = new TestAction();
LogUtils.log(LogUtils.Type.T, "test");
a.test();
}
}
Expect: no print for 'skip this method'.
Related
I am trying to spy private method with PowerMock but on the line when I define the what should be returned when the private method is called, it calls the method and I am getting and Null Pointer Exception. What PowerMock is calling real method on this line ?
myService= PowerMockito.spy(new MyService(myParam));
.....
PowerMockito.when(myService, "getCLientBy", anyString(), anyString(), anyString()).thenRetur`n(Client.of(setName, new HashSet<>())); // here it calls real method
Ensure that you prepare your class to be used in spy by adding #PrepareForTest(MyService.class)
#RunWith(PowerMockRunner.class)
// We prepare MyService for test because it's final
// or we need to mock private or static methods
#PrepareForTest(MyService.class)
public class YourTestCase {
//...
#Test
public void spyingWithPowerMock() {
MyService classUnderTest = PowerMockito.spy(new MyService(myParam));
//.....
// use PowerMockito to set up your expectation
PowerMockito.doReturn(Client.of(setName, new HashSet<>()))
.when(classUnderTest, "getClientBy", anyString(), anyString(), anyString());
//...
Also make sure provide the correct method name to be invoked.
#user1474111 and #Nkosi
I've built a small simulation of your example.
Maybe you also need to add the Client class in the PrepareForTest annotation.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ MyService.class, Client.class })
public class Example1Test {
#Test
public void testPowerMockito() throws Exception {
MyService myService = PowerMockito.spy(new MyService("myParam"));
PowerMockito.when(myService, "getClientBy", ArgumentMatchers.anyString(), ArgumentMatchers.anyString(),
ArgumentMatchers.anyString()).thenReturn(Client.of("setName", new HashSet<String>()));
myService.run();
Assert.assertEquals("setName", myService.getClient().getName());
}
}
public class MyService {
private Client client;
public MyService(String param) { }
private Client getClientBy(String a, String b, String c) {
return new Client(a + b + c);
}
public Client getClient() {
return this.client;
}
public void setClient(Client client) {
this.client = client;
}
public void run() {
setClient(getClientBy("A", "B", "C"));
}
}
public class Client {
private final String name;
public Client(String name) {
this.name = name;
}
public static Client of(String name, HashSet<String> hashSet) {
return new Client(name);
}
public String getName() {
return name;
}
}
I have this code in main class -
try {
extraPlayer = gson.fromJson(jsonResponse, ExtraPlayer.class);// this returns null
} catch (Exception e) {
e.printStacktrace();
}
Here extraPlayer is coming as null
I have mocked #Mock Gson gsonMock;
Here ExtraPlayer is a static class.
I have written this test code -
#Test
public void test() {
String jsonResponse = "{\"status\":\"waiting\",\"no\":\"12\"}";
when(playerHandlerMock.resetPlayer("someString", "someString", "1",true
)).thenReturn(jsonResponse);
Gson gsonMock = PowerMockito.mock(Gson.class);
ExtraPlayer extraPlayer = new ExtraPlayer();
extraPlayer.setNo("12");
extraPlayer.setStatus("Waiting");
PowerMockito.mockStatic(ResetModemResponse.class); // using this for static class but didn't work.
PowerMockito.when(gsonMock.fromJson(jsonResponse, ExtraPlayer.class)).thenReturn(extraPlayer);
playerMock.performWaiting();
}
ExtraPlayer.java
public static class ExtraPlayer{
String no;
String status;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getNo() {
return code;
}
public void setNo(String no) {
this.no = no;
}
}
I have added these annotations to the test class -
#RunWith(PowerMockRunner.class)
#PrepareForTest(Gson.class)
why extraPlayer is null ? please help/Suggest.
If you were to use the standard #Mock and #InjectMocks annotation with mockito, then yes, the framework would take care of the injection of the mock into the class under test (regardless of the existence of the setters etc.).
Another thing is the playerMock, which i assume is the class under test.
Do not mock the class under test, create a normal instance and then inject the dependencies... the performWaiting method does not seem to accept the response String, so you would have to inject that also somehow (unless you left some parts out):
#Test
public void test() {
// Arrange
String jsonResponse = "{\"status\":\"waiting\",\"no\":\"12\"}";
Gson gsonMock = PowerMockito.mock(Gson.class);
ExtraPlayer extraPlayer = new ExtraPlayer();
extraPlayer.setNo("12");
extraPlayer.setStatus("Waiting");
PowerMockito.when(gsonMock.fromJson(jsonResponse, ExtraPlayer.class)).thenReturn(extraPlayer);
Player player = new Player();
player.setGson(gsonMock);
player.setResponse(jsonResponse);
// Act
player.performWaiting();
// Assert ...
}
I needed to know that how to mock private method by using withInstanceOf in JMockit?
Here is the class I need to test.
package mockingPrivateMethodWithInstanceOf;
public class Simple
{
private String iAmPrivate(String argString)
{
return "Private Method";
}
public String publicCallsPrivate()
{
String string = "aString";
return iAmPrivate(string);
}
}
Here is the test class
public class SimpleTest
{
#Test
public void testPublicInvokesPrivate()
{
final Simple simple = new Simple();
new Expectations(simple)
{
{
Deencapsulation.invoke(simple, "iAmPrivate", withInstanceOf(String.class));
returns("Mocked method");
}
};
assertEquals("Mocked method", simple.publicCallsPrivate());
}
}
When test class is executed it says:
java.lang.IllegalArgumentException: Invalid null value passed as argument 0
I wrote a rather complex JavaFx 2 application for which I'd like to write a bunch of unit tests. Problem is when I try to conduct the tests I get a runtime error complaining about uninitialized toolkit.
From what I can tell I should somehow invoke Application.launch() in a #BeforeClass method but this causes a deadlock as Application.launch() doesn't return to calling thread.
So question is how should I initialize JavaFx?
This is the skeleton of the code that doesn't work:
public class AppTest extends Application {
#BeforeClass
public void initialize() {
launch(); //this causes a deadlock
}
#Test
public void test1() {
//conduct test here
}
#Test
public void test2() {
//conduct other test here
}
#Override
public void start(Stage arg0) throws Exception {
}
Thanks in advance!
From another question here on stackoverflow, I've made myself this little helper class:
import javafx.application.Application;
import javafx.stage.Stage;
public class JavaFXInitializer extends Application {
private static Object barrier = new Object();
#Override
public void start(Stage primaryStage) throws Exception {
synchronized(barrier) {
barrier.notify();
}
}
public static void initialize() throws InterruptedException {
Thread t = new Thread("JavaFX Init Thread") {
public void run() {
Application.launch(JavaFXInitializer.class, new String[0]);
}
};
t.setDaemon(true);
t.start();
synchronized(barrier) {
barrier.wait();
}
}
}
which can then be used easily in a #BeforeClass setup method:
#BeforeClass
public void setup() throws InterruptedException {
JavaFXInitializer.initialize();
}
The main think is to consider your tests to be run inside an FX thread. When you create a class extends Application, you create in fact a process. This is what you want to test.
So to launch some unit tests on an Application, first create an FXAppTest that extends Application and then inside FXAppTest you launch your unit test. Here is the idea.
Here is an example with JUnit. I create a Runner that launch the test inside an FXApp for test.
Here is an example of code for FxApplicationTest (we launch unit test inside it)
public class FxApplicationTest extends Application {
private volatile boolean isStopped;
#Override
public void start(final Stage stage) {
StackPane root = new StackPane();
Scene scene = new Scene(root, 10, 10);
stage.setScene(scene);
}
public void startApp() {
launch();
}
public void execute(final BlockJUnit4ClassRunner runner, final RunNotifier notifier) throws InterruptedException {
isStopped = false;
Platform.runLater(new Runnable() {
#Override
public void run() {
runner.run(notifier);
isStopped = true;
}
});
while (!isStopped) {
Thread.sleep(100);
}
}
And the Runner :
import org.apache.log4j.Logger;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;
public class JUnitFxRunner extends Runner {
private final BlockJUnit4ClassRunner runner;
private final Logger LOGGER = Logger.getLogger(JUnitFxRunner.class);
public JUnitFxRunner(final Class<?> klass) throws InitializationError {
super();
runner = new BlockJUnit4ClassRunner(klass);
}
#Override
public Description getDescription() {
return Description.EMPTY;
}
#Override
public void run(final RunNotifier notifier) {
try {
final FxApplicationTest fxApplicationTest = new FxApplicationTest();
MyTestRunner runnable = new MyTestRunner(runner, notifier, fxApplicationTest);
new Thread(runnable).start();
Thread.sleep(100);
runnable.execute();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
private class MyTestRunner implements Runnable {
private final BlockJUnit4ClassRunner runner;
private final RunNotifier notifier;
private final FxApplicationTest fxApp;
public MyTestRunner(final BlockJUnit4ClassRunner runner, final RunNotifier notifier, final FxApplicationTest fxApp) {
this.runner = runner;
this.notifier = notifier;
this.fxApp = fxApp;
}
#Override
public void run() {
fxApp.startApp();
}
public void execute() throws InterruptedException {
fxApp.execute(runner, notifier);
}
}
}
Now, simply launch test using the runner :
import fr.samarie_projects.fx.utils.JUnitFxRunner;
#RunWith(JUnitFxRunner.class)
public class MainFxAppTest {
#org.junit.Test
public void testName() throws Exception {
MainFxApp fxApp = new MainFxApp();
fxApp.start(new Stage());
}
}
This unit test MainFxApp
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class MainFxApp extends Application {
#Override
public void start(final Stage stage) throws Exception {
StackPane root = new StackPane();
Scene scene = new Scene(root, 10, 10);
stage.setScene(scene);
}
public static void main(final String[] args) {
launch(args);
}
}
Sure, this code need to be reviewed. It is only to present the idea.
Well, considering that you might have your JavaFX app located at project-root/src/main/java/package/FXApp.java then you might have your tests located elsewhere like project-root/src/test/java/package/FXAppTest.java . This being the case, the FXAppTest class could call the FXApp class by initializing it using BeforeClass .
In theory you should be able to start your FX app with something like:
// imports located here that import junit 4.11+ packages (or TestNG)
public class FXAppTest {
#BeforeClass
public void initialize() {
FXApp fxa = new FXApp();
while ( fxa.isLoading() ) {
// do nothing
}
}
....
NOTE: Notice that FXAppTest does not extend Application here.
Now, if this doesn't clue you into the problem, you could enable JMX args on the JVM and then view the locked threads with JVisualVM.
My Jaxb has created a Enum class based on the XML schema set up.
**enum Fruit {
APPLE,ORANGE;
}**
I am using a SOAP UI to check my web service. Since it is a free form entry, if i give a wrong fruit say "Guva" then instead of throwing an exception it is returning it as null after doing the UnMarshalling.
How can i avoid this? Should i use custom enum class instead of JAXB generated one. Please give some example. i.e.
regards
sri
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
By default your JAXB (JSR-222) implementation will not fail on any conversion exceptions. If you are using the JAXB APIs to do the unmarshalling then you can set a ValidationEventHandler to catch any problems. Below is an example.
Root
package forum12147306;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Root {
private int number;
private Fruit fruit;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public Fruit getFruit() {
return fruit;
}
public void setFruit(Fruit fruit) {
this.fruit = fruit;
}
}
Fruit
package forum12147306;
public enum Fruit {
APPLE,
ORANGE;
}
Demo
package forum12147306;
import java.io.StringReader;
import javax.xml.bind.*;
public class Demo {
private static final String XML = "<root><number>ABC</number><fruit>Guva</fruit></root>";
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setEventHandler(new ValidationEventHandler() {
#Override
public boolean handleEvent(ValidationEvent validationEvent) {
System.out.println(validationEvent.getMessage());
//validationEvent.getLinkedException().printStackTrace();
return true;
}
});
Root root = (Root) unmarshaller.unmarshal(new StringReader(XML));
}
}
JAXB REFERENCE IMPLEMENTATION
Unfortunately there appears to be a bug in the JAXB RI as a validation event is not being through for the invalid enum value.
Not a number: ABC
Work Around
Write your own XmlAdapter to handle to conversion to/from the Fruit enum:
FruitAdapter
package forum12147306;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class FruitAdapter extends XmlAdapter<String, Fruit> {
#Override
public String marshal(Fruit fruit) throws Exception {
return fruit.name();
}
#Override
public Fruit unmarshal(String string) throws Exception {
try {
return Fruit.valueOf(string);
} catch(Exception e) {
throw new JAXBException(e);
}
}
}
Fruit
Use the #XmlJavaTypeAdapter annotation to associate the XmlAdapter with the Fruit enumb.
package forum12147306;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlJavaTypeAdapter(FruitAdapter.class)
public enum Fruit {
APPLE,
ORANGE;
}
New Output
Not a number: ABC
javax.xml.bind.JAXBException
- with linked exception:
[java.lang.IllegalArgumentException: No enum const class forum12147306.Fruit.Guva]
EclipseLink JAXB (MOXy)
Using MOXy both validation events are thrown. To specify MOXy as your JAXB provider see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html.
Exception Description: The object [ABC], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[number-->number/text()]] with descriptor [XMLDescriptor(forum12147306.Root --> [DatabaseTable(root)])], could not be converted to [class java.lang.Integer].
Internal Exception: java.lang.NumberFormatException: For input string: "ABC"
Exception Description: No conversion value provided for the value [Guva] in field [fruit/text()].
Mapping: org.eclipse.persistence.oxm.mappings.XMLDirectMapping[fruit-->fruit/text()]
Descriptor: XMLDescriptor(forum12147306.Root --> [DatabaseTable(root)])
Short answer based on original reply. You need to do 2 things
implement custom adapter to raise and exception
add event handler to fail unmarshalling
Fruit.java defines and uses the adapter
package forum12147306;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlJavaTypeAdapter(FruitAdapter.class)
public enum Fruit {
APPLE,
ORANGE;
}
class FruitAdapter extends XmlAdapter<String, Fruit> {
#Override
public String marshal(Fruit fruit) throws Exception {
return fruit.name();
}
#Override
public Fruit unmarshal(String string) throws Exception {
try {
return Fruit.valueOf(string);
} catch(Exception e) {
throw new JAXBException(e);
}
}
}
The event handler for unmarshaller that fails parsing on error - i.e it returns false (you might need to decide when to fail and when not to fail)
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setEventHandler(new ValidationEventHandler() {
#Override
public boolean handleEvent(ValidationEvent validationEvent) {
return false;
}
});
An alternative consists in generating XSD schemas as presented in here: how can i unmarshall in jaxb and enjoy the schema validation without using an explicit schema file.
Here is the snippet I stole from dolbysurnd:
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.Result;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.SAXException;
private static List<DOMResult> generateJaxbSchemas(JAXBContext context) throws IOException {
final List<DOMResult> domResultList = new ArrayList<>();
context.generateSchema(new SchemaOutputResolver() {
#Override
public Result createOutput(String ns, String file) throws IOException {
DOMResult domResult = new DOMResult();
domResult.setSystemId(file);
domResultList.add(domResult);
return domResult;
}
});
return domResultList;
}
private static Unmarshaller createUnmarshaller(JAXBContext context) throws SAXException, IOException, JAXBException {
Unmarshaller unmarshaller = context.createUnmarshaller();
List<DOMSource> domSourceList = new ArrayList<>();
for (DOMResult domResult : generateJaxbSchemas(context)) {
domSourceList.add(new DOMSource(domResult.getNode()));
}
SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = schemaFactory.newSchema(domSourceList.toArray(new DOMSource[0]));
unmarshaller.setSchema(schema);
return unmarshaller;
}
public void unmarshal(JAXBContext context, Reader reader) throws JAXBException, SAXException, IOException {
Unmarshaller unmarshaller = createUnmarshaller(context);
Object result = unmarshaller.unmarshal(reader);
}