I'm using EclEmma plugin for Eclipse, and the coverage report shows 0% coverage for an Enum I've defined,
public enum Call {
INSTANCE;
public int add(int a, int b) {
return a+b;
}
public int sub(int a,int b){
return a-b;
}
}
and my test case are like this
#Test
public void addTest(){
Call.INSTANCE.add(1, 2);
}
#Test
public void subTest(){
Call.INSTANCE.sub(1, 2);
}
Using Eclipse IDE for Java Developers Oxygen.3a Release (4.7.3a) that comes with EclEmma 3.1.0, after "Coverage As" => "JUnit Test" on "CallTest":
P.S. such tests without assertions are useless
Related
I've spent a few days trying to find out a solution, so I know all the basic answers
I've read the documentation, and I know, that #BeforeClass/#AfterClass is replaced with #BeforeAll/#AfterAll, #RunWith no longer exists; superseded by #ExtendWith
I've read all the topics here on the stackoverflow (removed links, since stackoverflow pretends it's a spam:(
I used to run some JUnit4 tests in the suites. Each Suite class Suite1.class, Suite2.class had several #Test methods and #BeforeClass/#AfterClass were running exactly before/after all the testing methods.
#RunWith(StopOnFailureSuite.class)
#Suite.SuiteClasses({
Test1.class,
Test2.class
})
public class TSuite_20 {
private static final byte SUITE_NUMBER = 20;
#BeforeClass
public static void setUpClass() {
//some logic for suite setup
}
#AfterClass
public static void tearDownClass() {
//some logic for teardown
}
}
As I wanted to use #ParameterizedTests I need to migrate to JUnit5.
And suddenly I realised, that exact the same behaviour, that used to be in JUnit4 is no more achievable.
[run some custom setup code; run several test classes, which may contain several #Test methods; run some custom tear down code];
Does anybody know (better with examples) an approach to make it with JUnit 5?
Option 1
This code will never execute BeforeAfterSuite#beforeAll and BeforeAfterSuite#afterAll
#ExtendWith(BeforeAfterSuite.class)
#Suite
#SelectClasses({
Test1.class,
Test2.class
})
public class TSuite_20 {
public static final byte SUITE_NUMBER = 20;
}
public class BeforeAfterSuite implements BeforeAllCallback, AfterAllCallback
/*,TestInstancePreConstructCallback, BeforeTestExecutionCallback,
AfterTestExecutionCallback, ExtensionContext.Store.CloseableResource*/ {
private static boolean started = false;
#Override
public void beforeAll(ExtensionContext context) {
if (!started) {
started = true;
//before stuff
}
}
#Override
public void afterAll(ExtensionContext context) throws Exception {
//after all;
}
}
Option 2
I was just curious, how will JUnit treat suite class if I put a test method into it...
This code will execute BeforeAfterSuite#beforeAll and BeforeAfterSuite#afterAll once, before and after TSuite_20#test
#ExtendWith(BeforeAfterSuite.class)
#Suite
#SelectClasses({
Test1.class,
Test2.class
})
public class TSuite_20 {
public static final byte SUITE_NUMBER = 20;
#Test
public void test() {
}
}
Option 3
We also can apply #ExtendWith(BeforeAfterSuite.class) per Test class which will results in a BeforeAfterSuite#beforeAll and BeforeAfterSuite#afterAll per Test class. (in this example - 2 times).
#ExtendWith(BeforeAfterSuite.class)
public class Test1 {
#Test
public void test11() {
}
#Test
public void test12() {
}
}
#ExtendWith(BeforeAfterSuite.class)
public class Test2 {
#Test
public void test21() {
}
#Test
public void test22() {
}
}
Option 4
I also give a shot for
a Suite class without #ExtendWith() and #BeforeAll + #AfterAll; (as expected nothing happened)`
a Suite class without #ExtendWith() and #BeforeAll + #Test + #AfterAll; (as expected single execution of BeforeAll/AfterAll for the specific Suite class)`
Option 5
Listeners were my last hope to achieve the desired behaviour.
I've created my own impl for LauncherSessionListener, just because I've thought it will allow me to execute smth exactly before tests start.
public class BeforeAfterSuiteLauncher implements LauncherSessionListener {
private static boolean started = false;
#Override
public void launcherSessionOpened(LauncherSession session) {
if (!started) {
started = true;
//before all
}
}
#Override
public void launcherSessionClosed(LauncherSession session) {
//after all
}
}
And I've added also some default impl CompositeLauncherSessionListener
Packages structure screenshot to show Java SPI configuration: LauncherSessionListener
For TestExecutionListener I've added two default impls, just to catch at least one Listener:
org.junit.platform.launcher.listeners.LoggingListener
org.junit.platform.launcher.listeners.SummaryGeneratingListener
and one custom
public class BeforeAfterExecutionListener implements TestExecutionListener {
#Override
public void testPlanExecutionStarted(TestPlan testPlan) {
//before all
}
#Override
public void testPlanExecutionFinished(TestPlan testPlan) {
//after all
}
}
Packages structure screenshot to show Java SPI configuration:TestExecutionListener
And only SummaryGeneratingListener was triggered!
What am I doing wrong? Why my BeforeAfterExecutionListener impl was not loaded and triggered?
P.S. All of the above code was executed under Intellij Idea 2021.1.3 Ultimate Edition
java version "1.8.0_341"
Java(TM) SE Runtime Environment (build 1.8.0_341-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.341-b10, mixed mode)
here is intelliJs command:
C:\Tools\jdk\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:61280,suspend=y,server=n -ea -Didea.test.cyclic.buffer.size=1048576 -javaagent:C:\Users\userName\AppData\Local\JetBrains\IntelliJIdea2021.1\groovyHotSwap\gragent.jar -javaagent:C:\Users\userName\AppData\Local\JetBrains\IntelliJIdea2021.1\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath C:\Users\userName\AppData\Local\Temp\classpath1705687115.jar com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 com.testdirectly.application.testcase.TSuite_20
Which results in JUnit5IdeaTestRunner
My gradle dependencies
dependencies {
//JUnit platform
// to group tests by package, by class name, by class name pattern, etc (use #Suite, #SelectClasses) :junit-platform-suite-api:1.9.2
// and to filter/discover and run them (SuiteLauncher, SuiteTestEngine, SuiteTestDescriptor) :junit-suite-engine:1.9.2
testImplementation "org.junit.platform:junit-platform-suite:1.9.2"
//Launcher, engine discovery
testImplementation "org.junit.platform:junit-platform-launcher:1.9.2"//to run tests
//JUnit Jupiter
//to use assertions and so on
testImplementation "org.junit.jupiter:junit-jupiter-api:5.9.2"
//to use #ParameterizedTest
testImplementation "org.junit.jupiter:junit-jupiter-params:5.9.2"
//Jupiter engine to run junit5 tests (JupiterTestEngine, Extensions, etc)
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.9.2"
}
Short answer
Option 5 works if you tweak it slightly (see below).
Long answer
Options 1 and 2 do not work because #ExtendWith is a Jupiter extension mechanism whereas #Suite triggers an engine of its own.
Test engines do not combine on the JUnit platform.
The same goes for option 4 since #BeforeAll and #AfterAll are Jupiter annotations.
Making Option 5 Work
First of all I'd suggest to use TestExecutionListener instead of LauncherSessionListener because the latter is still experimental.
Thus we have
package my.project.suites;
import org.junit.platform.launcher.*;
public class BeforeAfterSuiteListener implements TestExecutionListener {
#Override
public void testPlanExecutionStarted(TestPlan testPlan) {
System.out.println("before all");
}
#Override
public void testPlanExecutionFinished(TestPlan testPlan) {
System.out.println("after all");
}
}
The missing thing is now that you'll have to register BeforeAfterSuiteListener globally.
In classpath-based Java you do that through a resource file
META-INF/services/org.junit.platform.launcher.TestExecutionListener:
my.project.suites.BeforeAfterSuiteListener
Now before all and after all should show up in your output exactly once per test run.
I am using testNG for my selenium suite. There is a class having 35 test cases. But these test cases will execute only if a particular element is visible. If that element is not visible, the compiler goes through all the test cases. Is there any way that I could check that element visibility condition in an #BeforeClass annotation only. If an element is not visible, it should come out from that class and switch to the next one? It will save my time to go through all the test cases?
To achieve it use #Test annotation on class level and #BeforeTest to check element visibility so it will skip all test cases of class if it will not satisfy condition in #BeforeTest. See below code (it's tested and working).
#Test
public class SkipAllTestCases {
boolean elementNotVisible=true;
#BeforeTest
public void setUp() {
if (elementNotVisible) {
throw new SkipException("skipping test cases...");
}
}
public void test1() {
System.out.println("Test1");
}
public void test2() {
System.out.println("Test2");
}
public void test3() {
System.out.println("Test3");
}
}
Hope it will help.
You can use dependsOnMethods of TestNG Test annotation.
#Test
public void elementVisibleTest(){
//Fail or skip here
}
#Test(dependsOnMethods = {"elementVisibleTest"})
public void myOtherTest(){
//Do something
}
...
That means if elementVisibleTest fails or gets skipped all tests which depend on that test will be skipped too. The advantage of that would be that you can still have other tests in that class which will be executed (because they do not depend on elementVisibleTest).
One of the approach is add group to all such tests let say flow-1. Add before group method and throw exception if it doesn't match required condition. For example:
#BeforeGroups(groups="flow-1")
public void flow1() {
if(!requiredCondtionMatch) {
throw new SkipException("Flow not applicable");
}
}
If all tests falls under same class then you can use #BeforeClass as well.
Here's the code. The code in method test and test2 are different because the parameter passed to Test constructor are different. Actually, if I change any parameter to null, intellij stops reporting the duplication. Is there any way to fix this?
---- Updated --------
I pass 2 functions doing totally different things but intellij still reports duplication
public class TestMain {
public void test(int a)
{
System.out.println("haha");
System.out.println("hahaa");
TestMain testMain = new TestMain();
new Test(testMain::test3);
System.out.println("hahaaa");
}
public void test2(int a)
{
System.out.println("haha");
System.out.println("hahaa");
TestMain testMain = new TestMain();
new Test(testMain::still_dup);
System.out.println("hahaaa");
}
public void test3(int a) {
System.out.println("abc");
}
public void still_dup(int a) {
String b = "edf";
b.toLowerCase();
}
public class Test {
Test(handler h) {
}
}
public interface handler<M> {
void entitySelector(int a);
}
public static void main(String[] args) {
TestMain test = new TestMain();
test.test(1);
System.out.println("-------");
test.test2(2);
}
}
I think the best way to fix this is to replace test and test2 by a single method. You don't have to distinguish what to pass the constructor because it's the current method. This might be the reason why code duplication is reported. The methods can be replaced by a single one without problems.
I am looking at AspectJ to see if perhaps we can use it in our test suite.
We have a rather large third party Java communications library hardwired to use its own classes (which do not implement any interfaces) which in turn mean that we need a physical backend present and correctly configured to be able to run tests.
I am looking at our options for removing this restriction. A possibility would be to create a subclass of the troublesome classes and then ask AspectJ to simply replace "new X" with "new OurSubclassOfX" when loading the third party library, but I am new to AspectJ and from my brief skimming of the documentation this is not a typical use case.
Can AspectJ do this? What would the configuration snippet be?
Yes, this is possible. Let us assume you have a hard-wired class, possibly fetching something from a database, and want to mock it via an aspect:
package de.scrum_master.aop.app;
public class HardWired {
private int id;
private String name;
public HardWired(int id, String name) {
this.id = id;
this.name = name;
}
public void doSomething() {
System.out.println("Fetching values from database");
}
public int getSomething() {
return 11;
}
#Override
public String toString() {
return "HardWired [id=" + id + ", name=" + name + "]";
}
}
Then there is a little driver application using that very class (not an interface):
package de.scrum_master.aop.app;
public class Application {
public static void main(String[] args) {
HardWired hw = new HardWired(999, "My object");
System.out.println(hw);
hw.doSomething();
System.out.println(hw.getSomething());
}
}
The output is as follows:
HardWired [id=999, name=My object]
Fetching values from database
11
Now you define your derived mock class which should replace the original for testing purposes:
package de.scrum_master.aop.mock;
import de.scrum_master.aop.app.HardWired;
public class HardWiredMock extends HardWired {
public HardWiredMock(int id, String name) {
super(id, name);
}
#Override
public void doSomething() {
System.out.println("Mocking database values");
}
#Override
public int getSomething() {
return 22;
}
#Override
public String toString() {
return "Mocked: " + super.toString();
}
}
And finally you define an aspect with a simple pointcut and advice to replace the original value during each constructor call:
package de.scrum_master.aop.aspect;
import de.scrum_master.aop.app.HardWired;
import de.scrum_master.aop.mock.HardWiredMock;
public aspect MockInjector {
HardWired around(int p1, String p2) : call(HardWired.new(int, String)) && args(p1, p2) {
return new HardWiredMock(p1, p2);
}
}
The output changes as desired:
Mocked: HardWired [id=999, name=My object]
Mocking database values
22
You do that once per class and constructor and are fine. In order to generalise the approach you would need joinpoint properties and, depending on how far you want to go, maybe reflection, but this here is pretty straightforward. Enjoy!
I try testing my LocalServiceUtil classes, generated by service builder, with PowerMock but always getting 'null' or '0' from Util's methods.
Test class
#RunWith(PowerMockRunner.class)
#PrepareForTest(EntityLocalServiceUtil.class)
public class EntityTest {
#Test
public void testGetAnswer() throws PortalException, SystemException {
PowerMockito.mockStatic(EntityLocalServiceUtil.class);
assertEquals("hello", EntityLocalServiceUtil.getHello());
}
}
Util class contains
public static java.lang.String getHello() {
return getService().getHello();
}
and this service working correctly on deployed portlet. What i do wrong?
You have forgot to mock the methode:
#Test
public void testGetAnswer() throws PortalException, SystemException {
PowerMockito.mockStatic(EntityLocalServiceUtil.class);
when(EntityLocalServiceUtil.getHello()).thenReturn("hello"); // <- here
assertEquals("hello", EntityLocalServiceUtil.getHello());
}