AssertJ-Swing and Junit 5 support - java

I'm currently working at a Java application that I'm testing using JUnit Jupiter. I am starting to work at the GUI and I was wondering if it was possible to use AssertJ-Swing with JUnit 5.
As a matter of fact I have found an open issue on AssertJ-Swing GitHub page.
The suggestion they give is to define a GUITestExtension like so:
import org.assertj.swing.junit.runner.ImageFolderCreator;
import org.junit.jupiter.api.extension.Extension;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.InvocationInterceptor;
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
import java.lang.reflect.Method;
import static org.assertj.swing.annotation.GUITestFinder.isGUITest;
import static org.assertj.swing.junit.runner.Formatter.testNameFrom;
/**
* Understands a JUnit 5 extension that takes a screenshot of a failed GUI test.
* The Junit 4 runner is available in {#link org.assertj.swing.junit.runner.GUITestRunner}.
*
* #see assertj-swing #259
* #author William Bakker
*/
public class GUITestExtension implements Extension, InvocationInterceptor {
private final FailureScreenshotTaker screenshotTaker;
public GUITestExtension() {
screenshotTaker = new FailureScreenshotTaker(new ImageFolderCreator().createImageFolder());
}
#Override
public void interceptTestMethod(
Invocation<Void> invocation,
ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext)
throws Throwable {
try {
invocation.proceed();
} catch (Throwable t) {
takeScreenshot(invocationContext.getExecutable());
throw t;
}
}
private void takeScreenshot(Method method) {
final Class<?> testClass = method.getDeclaringClass();
if (!(isGUITest(testClass, method)))
return;
screenshotTaker.saveScreenshot(testNameFrom(testClass, method));
}
}
I am a bit familiar with the GUITestRunner that can be used with JUnit 4, but I have no idea on how to replace it with this.
Note:
Usually GUITestRunner is used like so with JUnit 4:
import org.assertj.swing.junit.runner.GUITestRunner;
import org.assertj.swing.junit.testcase.AssertJSwingJUnitTestCase;
import org.junit.runner.RunWith;
import org.assertj.swing.edt.GuiActionRunner;
import org.assertj.swing.fixture.FrameFixture;
#RunWith(GUITestRunner.class)
public class WelcomeSwingViewTest extends AssertJSwingJUnitTestCase{
private FrameFixture window;
private WelcomeSwingView welcomeSwingView;
#Override
protected void onSetUp() {
GuiActionRunner.execute(() -> {
welcomeSwingView = new WelcomeSwingView();
return welcomeSwingView;
});
window = new FrameFixture(robot(), welcomeSwingView);
window.show();
}
}
Any help is appreciated.

Assuming that the GUITestExtension mentioned in the issue is defined in your codebase, it could be registered in the following way:
#Test
#ExtendWith(GUITestExtension.class)
void test() {
...
}
More can be found in the extension model section of the JUnit 5 documentation.
Ideally, the extension should come directly from AssertJ Swing, but the project lead has no longer time for it, unfortunately, therefore we are looking for committers.
If anyone is interested, feel free to get in touch on GitHub.

I changed my test class according to Stefano's answer, and now everything is working. In case anyone needs it my test class code is something like this:
import org.assertj.swing.core.matcher.JLabelMatcher;
import org.assertj.swing.edt.GuiActionRunner;
import org.assertj.swing.fixture.FrameFixture;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.assertj.swing.annotation.GUITest;
#ExtendWith(GUITestExtension.class)
class WelcomeSwingViewTest {
private FrameFixture window;
private WelcomeSwingView welcomeSwingView;
#BeforeAll
static void setUpOnce() {
FailOnThreadViolationRepaintManager.install();
}
#BeforeEach
void setup() {
GuiActionRunner.execute(() -> {
welcomeSwingView = new WelcomeSwingView();
return welcomeSwingView;
});
window = new FrameFixture(welcomeSwingView);
window.show();
}
#AfterEach
void clean() {
window.cleanUp();
}
#Test #GUITest
void testControlsInitialStates() {
window.label(JLabelMatcher.withText("label"));
}
}
Of course you also have to import the GUITestExtension (defined as in my question) to your test class. Also the test is successful because in my view I have a label with text "label".

Related

JUnit setUp doesn't create object

Why do I get a NullPointerExeption for testManuscript when trying to run my test?
This is my Manuscript.java:
package org.lhoffjann;
public class Manuscript {
private String msID;
private String path;
public void setMSid(String msID){
this.msID = msID;
}
public String getMSid() {
return this.msID;
}
}
This is my ManuscriptTest.java:
package org.lhoffjann;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ManuscriptTest {
private static Manuscript testManuscript;
#Before
public void setUp(){
testManuscript = new Manuscript();
}
#Test
public void testGetMSid() {
testManuscript.setMSid("1234");
assertTrue("1234" == testManuscript.getMSid());
}
}
You have imported #Test from JUnit 5, while you're using #Before from JUnit 4, that combination doesn't work. You need to choose which JUnit version you want to use, 4 or 5, and then consistently import classes from that JUnit version. I would recommend using JUnit 5, and removing all JUnit 4 dependencies from your classpath, or at least configure your IDE to not suggest those imports.
For this specific case, replace #Before (org.junit.Before) with #BeforeEach (org.junit.jupiter.api.BeforeEach).
In the example as shown, you don't even need this setUp method, as each test-execution gets its own instance of the test class. You can use:
private Manuscript testManuscript = new Manuscript();
That is, remove static, initialize the field directly, and remove the setUp method.
Even if you continue to use the setUp method, I recommend removing the static, so testManuscript is an instance field, like it is actually used.
You have mixed Junit4 with Junit5. You should use only one version.
Junit4 or
package org.lhoffjann;
import org.junit.Before;
import org.junit.Test;
import org.junit.Assert;
public class ManuscriptTest {
private static Manuscript testManuscript;
#Before
public void setUp(){
testManuscript = new Manuscript();
}
#Test
public void testGetMSid() {
testManuscript.setMSid("1234");
Assert.assertEquals("1234",testManuscript.getMSid());
}
or
Junit5
package org.lhoffjann;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class ManuscriptTest {
private static Manuscript testManuscript;
#BeforeEach
public void setUp() {
testManuscript = new Manuscript();
}
#Test
void testGetMSid() {
testManuscript.setMSid("1234");
Assertions.assertEquals("1234", testManuscript.getMSid());
}
}

Is there a way to get the list of scenarios that are to be run in the #BeforeClass annotation in cucumber JVM

I have got a requirement to get the list of all the scenarios that are to be executed based on the tag I provided in cucumber Test runner. However I have to get this list before tests start execution.
I know there is a tag called "#BeforeClass" but I am not sure if I can use to get the list of all the scenarios that are going to be run. For example something like this
#BeforeClass
public void intialize(Scenario[] scenario) throws Exception { }
Below is the code for me test runner class
package com.automation.cucumber;
import com.automation.Utils;
import io.cucumber.java.Scenario;
import io.cucumber.testng.*;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import java.io.File;
#CucumberOptions(features = "features/amazon"
,glue="com.automation.cucumber"
,tags = "#tt"
,dryRun = true
, plugin = {"json:target/cucumber-reports/cucumber.json"})
public class CucumberTestRunner extends AbstractTestNGCucumberTests {
static String resultFolder;
#DataProvider(parallel = true)
public Object[][] scenarios() {
return super.scenarios();
}
#BeforeClass
public void intialize() throws Exception {
resultFolder = Utils.createTestReportFolder();
if(resultFolder==null)
{
throw new Exception("Unable to create a result folder");
}
System.out.println();
}
}
You may have to implement EventListener class to get that information and do dryRun = true in your Runner class in #CucumberOptions
Quoting from a question that can help you achieve what you need
public class DryRunPlugin implements EventListener {
#Override
public void setEventPublisher(EventPublisher publisher) {
publisher.registerHandlerFor(TestCaseStarted.class, this::handleCaseStarted);
}
private void handleCaseStarted(TestCaseStarted event) {
System.out.println(event.getTestCase().getUri());
System.out.println(event.getTestCase().getName());
System.out.println(event.getTestCase().getScenarioDesignation());
event.getTestCase().getTags().stream().forEach(t ->
System.out.println(t.getName()));
}
}

The Junit test fails in Netbeans 11.3 IDE "Could not find or load main class"

I just installed Netbeans 11.3, on windows 10 running JDK 14. I tried to follow the simple 10 minutes learning tutorial provided at https://netbeans.apache.org/kb/docs/java/javase-intro.html just to get my feet wet. Everything worked fine until I reached the section under "Creating JUnits Tests". The IDE does a good job in generating the code for the JUnit test class, however, the test fails with Could not find or load main class error. Here is the stack trace from the output window:
compile-test:
Created dir: C:\Users\....\Documents\NetBeansProjects\MyLib\build\test\results
Testsuite: org.me.mylib.LibClassTest
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.152 sec
Testcase: initializationError(org.me.mylib.LibClassTest): Caused an ERROR
No runnable methods
java.lang.Exception: No runnable methods
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
Test org.me.mylib.LibClassTest FAILED
The exception seems to take place during the test initialization, internal to the JUnit framework.
Here is the code for the test class (LibClassTest from the file LibClassTest.java) generated by the IDE per tutorial example:
package org.me.mylib;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* #author hrh74
*/
public class LibClassTest {
public LibClassTest() {
System.out.println("Creating LibClassTest");
}
#BeforeAll
public static void setUpClass() {
}
#AfterAll
public static void tearDownClass() {
}
#BeforeEach
public void setUp() {
}
#AfterEach
public void tearDown() {
}
/**
* Test of acrostic method, of class LibClass.
*/
#Test
public void testAcrostic() {
System.err.println("Running testAcrostic...");
String result = LibClass.acrostic(new String[]{"fnord", "polly", "tropism"});
assertEquals("Correct value", "foo", result);
}
}
Here is the code for the class to be tested by the JUnit per the tutorial example:
package org.me.mylib;
/**
*
* #author hrh74
*/
public class LibClass {
public static String acrostic(String[] args) {
StringBuffer b = new StringBuffer();
for (int i = 0; i < args.length; i++) {
if (args[i].length() > i) {
b.append(args[i].charAt(i));
} else {
b.append('?');
}
}
System.out.println("The content of the buffer " + b);
return b.toString();
}
}
Any insights would be great.
Thanks in advance.
Well, it turned out that the putative "JUnit 5" feature in Netbeans 11.3 is not working. The support from the Netbeans mailing list was able to reproduce the bug. The solution is to change the test class. The import statements having org.junit.jupiter should be supplanted by their corresponding org.junit statements. In addition, the JUnit 5 annotations need to change to their corresponding older version. Here is a working example:
package org.me.mylib;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
public class LibClassTest {
public LibClassTest() {
}
#BeforeClass
public static void setUpClass() {
}
#AfterClass
public static void tearDownClass() {
}
#Before
public void setUp() {
}
#After
public void tearDown() {
}
#Test
public void testAcrostic() {
System.err.println("Running testAcrostic...");
String result = LibClass.acrostic(new String[]{"fnord", "polly", "tropism"});
assertEquals("Correct value", "foo", result);
}
}

Mockito: Intercepting method call without reference to object

I want to test the following example code:
public class Example {
...
public void doStuff() {
...
Lift lift = new Lift();
lift.call(5);
...
}
...
}
How can I 'intercept' lift.call(5)?
Generally I would use when(lift.call(anyInt()).thenReturn(...), but I have no reference to the Lift object.
You can't do it with mockito alone. The cleanest solution is to refactor your code so you can have access to it. However if that's not an option then "power mockito" is what you want. Grab "powermock-api-mockito"+"powermock-module-junit4" and then something like this will do the trick:
import static org.mockito.Mockito.verify;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(Example.class)
public class ExampleTest {
private Example testSubject;
#Mock
private Lift lift;
#Test
public void testDoStuff() throws Exception {
testSubject.doStuff();
verify(lift).call(5);
}
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
PowerMockito.whenNew(Lift.class).withNoArguments().thenReturn(lift);
testSubject = new Example();
}
}
Can you modify the Example class? If yes, the simplest way would be to extract the Lift dependency and provide it via constructor. Like this:
public class Example {
private final Lift lift;
public Example(Lift lift) {
this.lift = lift;
}
public void doStuff() {
this.lift.call(5);
}
}
Then you can stub lift as you want since now you have access to the instance.

Eclipse replace Assertions with StricAssertions when organizing imports

We have an import problem with Eclipse :
the test class uses Assertions.assertThat
When hitting Ctrl + Shift + O to organize the imports, Eclipse replace Assertions.assertThat with StrictAssertions.assertThat
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
public class TheTest {
#Test
public void testName() {
assertThat(2).isEqualTo(2);
}
}
is replaced with :
import static org.assertj.core.api.StrictAssertions.assertThat; // change here !
import org.junit.Test;
public class TheTest {
#Test
public void testName() {
assertThat(2).isEqualTo(2);
}
}
And when we have some specific asserts that are only in Assertions (for lists), Eclipse add StrictAssertions to the imports.
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import org.junit.Test;
public class TheTest {
#Test
public void testName() {
assertThat(2).isEqualTo(2);
assertThat(new ArrayList<>()).isEmpty();
}
}
is changed to :
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.StrictAssertions.assertThat; // this import was added
import java.util.ArrayList;
import org.junit.Test;
public class TheTest {
#Test
public void testName() {
assertThat(2).isEqualTo(2);
assertThat(new ArrayList<>()).isEmpty();
}
}
It seems that Assertions extends StrictAssertions, so their is no problem using StrictAssertions, but why is Eclipse not using the extended class ?
Looks like, because assertThat(int actual) is defined in StrictAssertions and not hidden by Assertions, Eclipse decides to import from StrictAssertions.
Also, for organizing imports Eclipse seems to ignore Type Filters - so even that won't help.
It seems that Assertions extends StrictAssertions, so their is no problem using StrictAssertions
Not for your current setup, but StrictAssertions has been removed with AssertJ 3.2.0. So when upgrading to a newer version of AssertJ StrictAssertions will get in your way.
I'd suggest you upgrade to 3.2.0 or later, if it is possible with your project.

Categories

Resources