JavaFX application thread exits during JUnit test - junit

I'm testing a JavaFX application with JUnit, In most cases I use the #Rule approach from Basic JUnit test for JavaFX 8. However there are a couple of situations where this approach does not work, so I setup the JavaFX platform manually, and call Platform.runLater() where necessary.
What appears to be happening is that at some point the JavaFX application thread is disappearing, this means subsequent tests lockup as the Platform.runLater() calls never return - that's why I've added timeouts in example. I've proved this with calls to Thread.getAllStackTraces()
Yes I'm aware of JemmyFX, and I'll likely move to it soon, but I'd still like to understand what's going on here...
Code
public class JavaFxThreadJUnit {
private static boolean setup;
private Stage stage;
#Before
public void before() throws Exception {
setupJavaFX();
Platform.setImplicitExit(true);
CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
stage = new Stage();
stage.show();
latch.countDown();
});
latch.await(5, TimeUnit.SECONDS);
}
#After
public void after() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
stage.hide();
latch.countDown();
});
latch.await(5, TimeUnit.SECONDS);
}
#Test
public void foo() throws Exception {
// test stuff...
System.out.println("foo test: "
+ Thread.getAllStackTraces().keySet().stream().map(Thread::getName).collect(Collectors.toList()));
}
#Test
public void bar() throws Exception {
// test stuff...
System.out.println("bar test: "
+ Thread.getAllStackTraces().keySet().stream().map(Thread::getName).collect(Collectors.toList()));
}
// https://gist.github.com/andytill/3835914
public static void setupJavaFX() throws InterruptedException {
if (setup) {
return;
}
long timeMillis = System.currentTimeMillis();
final CountDownLatch latch = new CountDownLatch(1);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// initializes JavaFX environment
new JFXPanel();
latch.countDown();
}
});
System.out.println("javafx initialising...");
latch.await();
System.out.println("javafx is initialised in " + (System.currentTimeMillis() - timeMillis) + "ms");
setup = true;
}
}
Output... JavaFX Application Thread was there, then it's gone...
javafx initialising...
javafx is initialised in 327ms
bar test: [Thread-3, ReaderThread, AWT-Shutdown, AWT-Windows, Thread-2, Finalizer, JavaFX Application Thread, Signal Dispatcher, Java2D Disposer, AWT-EventQueue-0, main, Attach Listener, Reference Handler, QuantumRenderer-0]
foo test: [Thread-3, ReaderThread, Java2D Disposer, AWT-Windows, Thread-2, main, Finalizer, Attach Listener, Reference Handler, Signal Dispatcher]

Looks like the stage closing is triggering an "implicit exit". I'd still be interested to know why this doesn't also affect tests using the #Rule approach...
Workaround:
Platform.setImplicitExit(false)

Related

How to have 100% test coverage for function that calls invokeLater()?

I am using Junit4.
This is my test class:
import org.junit.Test;
public class UIUtilTest {
#Test
public void testMultiline() {
var multiLineText = "one\ntwo";
UIUtil.showError(multiLineText, "title");
assert true;
}
}
I have the following Jacoco coverage result:
How can I test the lambda that Jacoco is complaining about in order to hit 100% coverage?
Make test wait for dialog to pop. Having your implementation you can simply add another task to the EDT queue and wait for it to finish.
#Test
public void testMultiline() throws InterruptedException, InvocationTargetException {
String multiLineText = "one\ntwo";
UIUtil.showError(multiLineText, "title");
SwingUtilities.invokeAndWait(() -> {
//just wait, nothing more
});
assert true;
}

How to verify an internal method call using Powermock?

I am trying to use PowerMockito to test a save method by verifying an internal audit() method call.
This internal call is made by auditor object which is being instantiated in an init() method of the class. As it is not injected I will not be able to mock it directly. When I used Mockito to verify it always said "There were zero interaction with the mock".
Question:How exactly do I test the save feature? Kindly help!
public class DaoImpl implements Dao{
private Auditor auditor;
#InjectValue
private ObjectLoader loader;
#InjectValue
private ConfigurationProvider confProvider;
#PostConstruct
public void init() {
//Mock this object instantiation and verify audit is called once
auditor = new SyncAuditor(confProvider.getClientConfiguration(), new EventRegProvider());
}
#Override
public void save(final AuditEvt auditEvt) {
final AuditedEvent auditedEvent = builder.build();
auditor.audit(auditedEvent);
}
Test :
#RunWith(PowerMockRunner.class)
#PrepareForTest({ DaoImplTest.class })
#PowerMockIgnore("javax.management.*")
public class DaoImplTest extends PowerMockito {
#InjectMocks
private DaoImpl dataAccess;
#Mock
private SynchAuditor auditorMock;
#Before
public void setUp() throws Exception {
loader = ObjectLoader.init("JUNIT");
loader.bind(ConfigurationProvider.class, configurationProviderMock);
dataAccess = loader.newInstance(DaoImpl.class);
}
#After
public void tearDown() {
loader.release(dataAccess);
ConnectionMgr.disconnect("JUNIT");
}
#Test
public void testSaveAuditEvent() throws Exception {
PowerMockito.whenNew(SynchAuditor.class).
withArguments(Matchers.any(ClientConfiguration.class), Matchers.any(EventRegProvider.class)).thenReturn(this.auditorMock);
final AuditEvent event = AuditEvent.from(null, "principal", UUID.randomUUID().toString(), "randomText",
new AuditEvtDefn((long) 522, "234242", "234242fdgd", true), SUCCESS, null, new GregorianCalendar());
dataAccess.save(event);
Mockito.verify(auditorMock, times(1)).audit(Matchers.any(AuditedEvent.class));
}
Even PowerMockito.verifyNew says there were zero interaction
PowerMockito.verifyNew(SynchronousAuditor.class,times(1)).withArguments(Matchers.any(AuditorClientConfiguration.class),Matchers.any(EventRegistrationProvider.class));
So, I figured out that java reflection will help in such a situation. You will have to get hold onto the real object and then set mocked object to it.
final Field privateAuditorField = DaoImpl.class.getDeclaredField("auditor");
privateAuditorField.setAccessible(true);
privateAuditorField.set(dataAccess, auditorMock);
Now verify will run sucessfully.
Mockito.verify(auditorMock, Mockito.times(1)).audit(Matchers.any(AuditedEvent.class));

swing application opens and closes down immediately when invoked with assertJ command (TestNG + assertJ Swing)

Trying assertJ-swing for UI testing of java-swing based application.
Situation: Sample application in JavaApp.java (with Main class) works fine when it is invoked from this java file (running it as Java application). But when it is invoked from TestNG with assertj-swing's command:
application(JavaApp.class).start();
the application opens up but closes down immediately.
Question: Is it the only approach? Please suggest resolution or any other approach to launch the application and keep it open so further operations can be performed.
JavaApp:
package jdialogdemo;
import java.awt.*;
import java.awt.event.*;
import javax.lang.model.util.SimpleElementVisitor6;
import javax.swing.*;
public class JavaApp {
public static void main(String[] args) throws Exception {
final JFrame frame = new JFrame("JDialog Demo");
final JButton btnLogin = new JButton("Click to login");
btnLogin.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e) {
LoginDialog loginDlg = new LoginDialog(frame);
loginDlg.setVisible(true);
// if logon successfully
if(loginDlg.isSucceeded()){
btnLogin.setText("Hi " + loginDlg.getUsername() + "!");
}
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(700, 200);
frame.setLocationRelativeTo(null);
frame.setLayout(new FlowLayout());
frame.getContentPane().add(btnLogin);
frame.setVisible(true);
}
}
AssertJ-Swing verifies that you only do access swing components on the EDT (as required because Swing is not thread safe, see Concurrency in Swing - Initial threads).
Your main method violates this (by constructing the UI from the main thread) and therefore AssertJ-Swing fails with an exception.
To correct the problem your main method should look like this:
public class JavaApp {
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(() -> {
final JFrame frame = new JFrame("JDialog Demo");
final JButton btnLogin = new JButton("Click to login");
//...
});
}
}

Unit testing a Play controller using mocks

The title pretty much says it all. I would like to set up a traditional JUnit test to mock a controller's dependencies and run tests against actions.
I've found that I can achieve my goal like this:
public class AccountsControllerTest {
private controllers.Accounts accountsController;
#Test
public void test() {
running(fakeApplication(), new Runnable() {
public void run() {
accountsController = new controllers.Accounts();
accountsController.setAccountsWorkflow(mock(workflow.Accounts.class));
}
});
}
}
The obvious problem here is that I'm instantiating my class under test and injecting mock dependencies from the test method itself, when I should be doing that in the setup() method. It seems that the setup() method is useless if I'm going to test my controller in a traditional way.
Of course I can test controllers the way Play recommends, but my application is dependent on an external SOAP web service, so I need unit tests to show that our code is working when their servers are down.
So, what's the best way to unit test a Play controller using mocks while still taking advantage of setup() and teardown() methods?
Edit
I realize I'm assuming some knowledge here, so for those who are unaware, controller instantiation in a unit test must be wrapped in a running() function or Play! will throw a runtime exception saying that no application has been started.
You could accomplish this using Mockito and Play's FakeApplication and setting the static Http.Context variable.
This way you can write the test like all other JUnit test.
Example:
...
import static play.test.Helpers.status;
import play.test.FakeApplication;
import play.test.Helpers;
import play.mvc.Http;
import play.mvc.Result;
...
#RunWith(MockitoJUnitRunner.class)
public class ApplicationTest {
public static FakeApplication app;
#Mock
private Http.Request request;
#BeforeClass
public static void startApp() {
app = Helpers.fakeApplication();
Helpers.start(app);
}
#Before
public void setUp() throws Exception {
Map<String, String> flashData = Collections.emptyMap();
Http.Context context = new Http.Context(request, flashData, flashData);
Http.Context.current.set(context);
}
#Test
public void testIndex() {
final Result result = Application.index();
assertEquals(play.mvc.Http.Status.OK, status(result));
}
#AfterClass
public static void stopApp() {
Helpers.stop(app);
}

To invokeLater() or Not

I was writing an example to showcase the usage of SwingUtilities.invokeLater(). I came to realize this simple example (code included) I have written didn't warranty the use of invokeLater(). I do encounter there were times I needed to use invokeLater() but I forgotten where and when I used. I also understand that in a non EDP thread I should use invokeLater() but in my case I don't seem to need that and it worked fine. I was hoping anyone advise me why I don't need to use invokeLater() in this piece of code. I hope there is no bug in my showcase code.
Btw, I am using JDK 1.6 / 1.7 in Linux and Windows.
Thanks.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class HelloButton {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setLayout(new FlowLayout());
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JSplitPane pane = new JSplitPane();
f.add(pane);
final JLabel clickMessage = new JLabel("No Message at " + System.currentTimeMillis());
pane.setLeftComponent(clickMessage);
JButton clickMe = new JButton("Click me");
clickMe.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
threadedIntensiveProcess(clickMessage);
// intensiveProcess(clickMessage);
}
});
pane.setRightComponent(clickMe);
f.pack();
f.setVisible(true);
}
static private void threadedIntensiveProcess(final JLabel label)
{
new Thread(new Runnable() {
#Override
public void run() {
System.out.println("UI Thread : " + SwingUtilities.isEventDispatchThread());
intensiveProcess(label);
}
}).start();
}
static private void intensiveProcess(JLabel label)
{
label.setText("was clicked at " + System.currentTimeMillis());
for (int i = 0; i < 3; i++)
{
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
label.setText("was updated at " + System.currentTimeMillis());
}
System.out.println(label.getText());
}
}
There are two situations here where you should use invokeLater.
The creation of the UI.
The update of the JLabel.
The whole creation of the UI should be done in the EDT. In ancient Swing times it was said that you could do any creation until show or setVisible(true) in the main thread as no threading issues could arise up to that point. As this is and was doubtful this is now discouraged; it may work -obviously, as in your case- but there is no guarantee.
You are lucky that setText in JLabel behaves well in this context. As it is not guaranteed by the API that the method is threadsafe you should call this method in the EDT like any other call to Swing methods.
So, in conclusion: You have a simple example that seems to work - because it is simple and you are lucky. Don't rely on such "tests" but on the documentation. If your showcase involves the presentation of the code then you have to move the calls to the EDT for not being wrong.
I don't understand why your code shouldn't "warrant" the use of invokeLater.