How do I use JUnitPerf with JWebUnit and JUnit 4? - java

I have a series of functional tests against a web application that correctly run, but each require the class level setup and teardown provided with the #BeforeClass and #AfterClass annotations, and hence require JUnit 4.0 or above.
Now I want to perform load testing using a small number of these functional tests, which simulate a large number of users requesting the related page of the web application. In order for each user to have their own "simulated browser" in JWebUnit, I need to use a TestFactory in JUnitPerf to instantiate the class under test, but since JUnit 4 tests are annotated with #Test instead of being derived from TestCase, I'm getting a TestFactory must be constructed with a TestCase class exception.
Is anyone successfully using JUnitPerf and its TestFactory with JUnit 4? And what is the secret sauce that lets it all work?

You need a JUnit4 aware TestFactory. I've included one below.
import junit.framework.JUnit4TestAdapter;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import com.clarkware.junitperf.TestFactory;
class JUnit4TestFactory extends TestFactory {
static class DummyTestCase extends TestCase {
public void test() {
}
}
private Class<?> junit4TestClass;
public JUnit4TestFactory(Class<?> testClass) {
super(DummyTestCase.class);
this.junit4TestClass = testClass;
}
#Override
protected TestSuite makeTestSuite() {
JUnit4TestAdapter unit4TestAdapter = new JUnit4TestAdapter(this.junit4TestClass);
TestSuite testSuite = new TestSuite("JUnit4TestFactory");
testSuite.addTest(unit4TestAdapter);
return testSuite;
}
}

Related

Trouble with JUnit

Whenever I create a new JUnit Test Case it generates like this:
import junit.framework.TestCase;
public class Test extends TestCase {
}
But this isn't correct. There isn't even an #Test generated, and when I put it in myself I get a type mismatch error (cannot convert from Test to annotation). Any help?
Edit:
import static org.junit.Assert.*;
public class Test {
#org.junit.Test
public void test() {
fail("Not yet implemented");
}
}
You are not using the right version of JUnit. Check the version you are using. Annotations are available in JUnit 4 and not available in JUnit 3

JUNIT : run setup only once for a large number of test classes

I have a class, which I use as a basis for my unit tests. In this class I initialize the whole environment for my tests, setting up database mappings, enter a number of database records across multiple tables, etc. That class has a method with a #BeforeClass annotation which does the initialization. Next thing, I extend that class with specific classes in which I have #Test methods.
My question is, since the before class is exactly the same for all these test classes, how can I ensure that they are run only once for all the tests.
One simple solution is that I could keep all the tests in one class. However, the number of tests is huge, also they are categorised based on functional heads. So they are located in different classes. However since they need the exact same setup, they inherit the #BeforeClass. As a result the whole setup is done at least once per test class, taking much more time in total than I would prefer.
I could, though, put them all in various subpackages under one package, hence if there is a way, how I can run set up once for all the tests within that package, it would be great.
With JUnit4 test suite you can do something like this :
#RunWith(Suite.class)
#Suite.SuiteClasses({ Test1IT.class, Test2IT.class })
public class IntegrationTestSuite
{
#BeforeClass
public static void setUp()
{
System.out.println("Runs before all tests in the annotation above.");
}
#AfterClass
public static void tearDown()
{
System.out.println("Runs after all tests in the annotation above.");
}
}
Then you run this class as you would run a normal test class and it will run all of your tests.
JUnit doesn't support this, you will have to use the standard Java work-arounds for singletons: Move the common setup code into a static code block and then call an empty method in this class:
static {
...init code here...
}
public static void init() {} // Empty method to trigger the execution of the block above
Make sure that all tests call init(), for example my putting it into a #BeforeClass method. Or put the static code block into a shared base class.
Alternatively, use a global variable:
private static boolean initialize = true;
public static void init() {
if(!initialize) return;
initialize = false;
...init code here...
}
Create one base class for all tests:
public class BaseTest {
static{
/*** init code here ***/
}
}
and every test should inherit from it:
public class SomeTest extends BaseTest {
}
You can make one BaseTest class with a #BeforeClass method, then have all the other tests inherit from it. This way, when each test object is constructed, #BeforeClass gets executed.
Also avoid executing it just once for all the test suite, since all the test cases should be independent. #BeforeClass should execute only once each test case, not test suite.
If you can tolerate adding spring-test to your project, or you are using it already, then a good approach is to use the technique described here: How to load DBUnit test data once per case with Spring Test
Not sure if anyone still is using JUnit and trying to fix it without using Spring Runner (aka no spring integration). TestNG has this feature. But here is a JUnit based solution.
Create a RunOnce per thread operation like so. This maintains a list of classes for which the operation has run.
public class RunOnceOperation {
private static final ThreadLocal t = new ThreadLocal();
public void run(Function f) {
if (t.get() == null) {
t.set(Arrays.asList(getClass()));
f.apply(0);
} else {
if (!((List) t.get()).contains(getClass())) {
((List) t.get()).add(getClass());
f.apply(0);
}
}
}
}
Back in your unit test
#Before
public beforeTest() {
operation.run(new Function<Integer, Void>() {
#Override
public Void apply(Integer t) {
checkBeanProperties();
return null;
}
});
}
private void checkBeanProperties() {
//I only want to check this once per class.
//Also my bean check needs instance of the class and can't be static.
}
My function interface is like this:
interface Function<I,O> {
O apply(I i);
}
When you use this way, you can perform operations once per class using ThreadLocal.

JUnit suite runner to execute one method

I have a test suite that runs all test classes
#RunWith(Suite.class)
#Suite.SuiteClasses({TestClass1.class, TestClass1.class})
}
public class AllTests extends TestCase {
public AllTests(String name) {
super(name);
}
public static TestSuite suite() {
TestSuite suite = new TestSuite("com.myapp.test.AllTests");
return suite;
}
}
is it possible to implement a custom runner that will run only one method, say "onlyMethodToRun", from every class in the suite?
Yes. Suite.java implements a test runner that examines the classes listed in #Suite.SuiteClasses and uses RunnerBuilders to find every test method. You should be able to reuse a lot of JUnit's code to implement a Runner that instead only checks for a single method on every class and perhaps uses a subclass of BlockJUnit4ClassRunner that overrides computeTestMethods to only attempt a single method.

JUnit: how to avoid "no runnable methods" in test utils classes

I have switched to JUnit4.4 from JUnit3.8. I run my tests using ant, all my tests run successfully but test utility classes fail with "No runnable methods" error. The pattern I am using is to include all classes with name *Test* under test folder.
I understand that the runner can't find any method annotated with #Test attribute. But they don't contain such annotation because these classes are not tests.
Surprisingly when running these tests in eclipse, it doesn't complain about these classes.
In JUnit3.8 it wasn't a problem at all since these utility classes didn't extend TestCase so the runner didn't try to execute them.
I know I can exclude these specific classes in the junit target in ant script. But I don't want to change the build file upon every new utility class I add. I can also rename the classes (but giving good names to classes was always my weakest talent :-) )
Is there any elegant solution for this problem?
Annotate your util classes with #Ignore. This will cause JUnit not to try and run them as tests.
My specific case has the following scenario. Our tests
public class VenueResourceContainerTest extends BaseTixContainerTest
all extend
BaseTixContainerTest
and JUnit was trying to run BaseTixContainerTest. Poor BaseTixContainerTest was just trying to setup the container, setup the client, order some pizza and relax... man.
As mentioned previously, you can annotate the class with
#Ignore
But that caused JUnit to report that test as skipped (as opposed to completely ignored).
Tests run: 4, Failures: 0, Errors: 0, Skipped: 1
That kind of irritated me.
So I made BaseTixContainerTest abstract, and now JUnit truly ignores it.
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
Assuming you're in control of the pattern used to find test classes, I'd suggest changing it to match *Test rather than *Test*. That way TestHelper won't get matched, but FooTest will.
To prevent JUnit from instantiating your test base class just make it
public abstract class MyTestBaseClass { ... whatever... }
(#Ignore reports it as ignored which I reserve for temporarily ignored tests.)
If this is your base test class for example AbstractTest and all your tests extends this then define this class as abstract
If it is Util class then better remove *Test from the class rename it is MyTestUtil or Utils etc.
Be careful when using an IDE's code-completion to add the import for #Test.
It has to be import org.junit.Test and not import org.testng.annotations.Test, for example. If you do the latter, you'll get the "no runnable methods" error.
Ant now comes with the skipNonTests attribute which was designed to do exactly what you seem to be looking for. No need to change your base classes to abstract or add annotations to them.
What about adding an empty test method to these classes?
public void avoidAnnoyingErrorMessageWhenRunningTestsInAnt() {
assertTrue(true); // do nothing;
}
In your test class if wrote import org.junit.jupiter.api.Test; delete it and write import org.junit.Test; In this case it worked me as well.
I was also facing a similar issue ("no runnable methods..") on running the simplest of simple piece of code (Using #Test, #Before etc.) and found the solution nowhere. I was using Junit4 and Eclipse SDK version 4.1.2. Resolved my problem by using the latest Eclipse SDK 4.2.2. I hope this helps people who are struggling with a somewhat similar issue.
I also faced the same issue once. In my case I was running my tests using Enclosed Runner of Junit. I created a class called SharedSetup to enable common features for my 2 test classes. But somehow facing the same issue.
#RunWith(Enclosed.class)
public class StructApprovalNodeTest {
abstract static class SharedSetup {
StructApprovalNode sut;
ExecutionContext ctx = mock(ExecutionContext.class);
DTDDAOService dtd = mock(DTDDAOService.class);
#Rule
public ExpectedException expectedException = ExpectedException.none();
#Before
public void before() throws Exception {
PowerMockito.mockStatic(ServiceHelper.class);
when(ServiceHelper.getService("dtd")).thenReturn(dtd);
when(ctx.getContextInstance()).thenReturn(mock(ContextInstance.class));
when(dtd.getLatestStructures(Matchers.anyInt(), Matchers.anyString(), Matchers.anyString())).thenReturn(
new ArrayList<Trade>());
sut = new StructApprovalNode();
spy(sut);
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({ ServiceHelper.class, StructApprovalNode.class })
#PowerMockIgnore("javax.management.*")
#PowerMockRunnerDelegate(Parameterized.class)
public static class ParamaterizedBatchTest extends SharedSetup {
private String batchName;
private String approvalStatus;
public ParamaterizedBatchTest(String batchName, String approvalStatus) {
this.batchName = batchName;
this.approvalStatus = approvalStatus;
}
#Parameterized.Parameters
public static Collection testValues() {
return Arrays.asList(new Object[][] {
{ "SDC_HK_AUTOMATION_BATCH", Constants.APRVLSTATUS_APPROVED },
{ "SDC_PB_AUTOMATION_BATCH", Constants.APRVLSTATUS_APPROVED },
{ "SDC_FX_AUTOMATION_BATCH", Constants.APRVLSTATUS_APPROVED }
});
}
#Test
public void test1_SDCBatchSourceSystems() throws Exception {
Trade trade = new Trade();
String tradeXml = FileHelper.getResourceFromJar("/testdata/SDC_BATCH_TRADE_XML.xml");
trade.setTradeXml(tradeXml);
trade.setTradeDoc(XmlHelper.createDocument(trade.getTradeXml()));
trade.setStatus(Constants.STATUS_LIVE);
trade.setSourceSystem(this.batchName);
when(ctx.getContextInstance().getVariable("trade")).thenReturn(trade);
when(ctx.getContextInstance().getTransientVariable("prevTrade")).thenReturn(null);
sut.execute(ctx);
PowerMockito.verifyPrivate(sut, times(1)).invoke("resetApprovalDetails", trade);
Assert.assertEquals(this.approvalStatus, trade.getApprovalStatus());
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({ ServiceHelper.class, StructApprovalNode.class })
#PowerMockIgnore("javax.management.*")
public static class NonParamaterizedBatchTest extends SharedSetup {
#Test
public void test2_PrevInvalidTrade() throws Exception {
expectedException.expect(Exception.class);
expectedException.expectMessage("External Id of STRUCTURE_TRADE cannot be changed.");
Trade trade = new Trade();
trade.setExternalId(123);
PrevTrade prevTrade = new PrevTrade();
prevTrade.setExternalId(1234);
when(ctx.getContextInstance().getVariable("trade")).thenReturn(trade);
when(ctx.getContextInstance().getTransientVariable("prevTrade")).thenReturn(prevTrade);
sut.execute(ctx);
}
#Test
public void test3_ValidPrevTrade() throws Exception {
Trade trade = new Trade();
String tradeXml = FileHelper.getResourceFromJar("/testdata/SDC_BATCH_TRADE_XML.xml");
trade.setTradeXml(tradeXml);
trade.setTradeDoc(XmlHelper.createDocument(trade.getTradeXml()));
trade.setStatus(Constants.STATUS_LIVE);
trade.setSourceSystem("BATCH");
trade.setExternalId(1277402441);
PrevTrade prevTrade = new PrevTrade();
prevTrade.setExternalId(1277402441);
when(ctx.getContextInstance().getVariable("trade")).thenReturn(trade);
when(ctx.getContextInstance().getTransientVariable("prevTrade")).thenReturn(prevTrade);
sut.execute(ctx);
PowerMockito.verifyPrivate(sut, times(1)).invoke("resetApprovalDetails", trade);
Assert.assertEquals("APPROVED", trade.getApprovalStatus());
}
#Test
public void test4_ValidPrevTradeAutoApprpve() throws Exception {
Trade trade = new Trade();
String tradeXml = FileHelper.getResourceFromJar("/testdata/SDC_BATCH_TRADE_XML_AUTO_APPRV.xml");
trade.setTradeXml(tradeXml);
trade.setTradeDoc(XmlHelper.createDocument(trade.getTradeXml()));
trade.setStatus(Constants.STATUS_LIVE);
trade.setSourceSystem("BATCH");
trade.setExternalId(1277402441);
PrevTrade prevTrade = new PrevTrade();
prevTrade.setExternalId(1277402441);
prevTrade.setApprovalStatus(Constants.APRVLSTATUS_NOTAPPROVED);
when(ctx.getContextInstance().getVariable("trade")).thenReturn(trade);
when(ctx.getContextInstance().getTransientVariable("prevTrade")).thenReturn(prevTrade);
sut.execute(ctx);
PowerMockito.verifyPrivate(sut, times(1)).invoke("resetApprovalDetails", trade);
Assert.assertEquals(prevTrade.getApprovalStatus(), trade.getApprovalStatus());
}
#Test
public void test5_tradeStatusDraft() throws Exception {
Trade trade = new Trade();
String tradeXml = FileHelper.getResourceFromJar("/testdata/SDC_BATCH_TRADE_XML.xml");
trade.setTradeXml(tradeXml);
trade.setTradeDoc(XmlHelper.createDocument(trade.getTradeXml()));
trade.setStatus(Constants.STATUS_DRAFT);
trade.setSourceSystem("BATCH");
trade.setExternalId(1277402441);
when(ctx.getContextInstance().getVariable("trade")).thenReturn(trade);
when(ctx.getContextInstance().getTransientVariable("prevTrade")).thenReturn(null);
sut.execute(ctx);
PowerMockito.verifyPrivate(sut, times(1)).invoke("resetApprovalDetails", trade);
Assert.assertEquals(Constants.APRVLSTATUS_NONE, trade.getApprovalStatus());
}
}
}
To solve the issue, I just removed the public modifier from the abstract super class SharedSetup and issue is fixed for good

Before and After Suite execution hook in jUnit 4.x

I'm trying to preform setup and teardown for a set of integration tests, using jUnit 4.4 to execute the tests. The teardown needs to be run reliably. I'm having other problems with TestNG, so I'm looking to port back to jUnit. What hooks are available for execution before any tests are run and after all tests have completed?
Note: we're using maven 2 for our build. I've tried using maven's pre- & post-integration-test phases, but, if a test fails, maven stops and doesn't run post-integration-test, which is no help.
Yes, it is possible to reliably run set up and tear down methods before and after any tests in a test suite. Let me demonstrate in code:
package com.test;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
#RunWith(Suite.class)
#SuiteClasses({Test1.class, Test2.class})
public class TestSuite {
#BeforeClass
public static void setUp() {
System.out.println("setting up");
}
#AfterClass
public static void tearDown() {
System.out.println("tearing down");
}
}
So your Test1 class would look something like:
package com.test;
import org.junit.Test;
public class Test1 {
#Test
public void test1() {
System.out.println("test1");
}
}
...and you can imagine that Test2 looks similar. If you ran TestSuite, you would get:
setting up
test1
test2
tearing down
So you can see that the set up/tear down only run before and after all tests, respectively.
The catch: this only works if you're running the test suite, and not running Test1 and Test2 as individual JUnit tests. You mentioned you're using maven, and the maven surefire plugin likes to run tests individually, and not part of a suite. In this case, I would recommend creating a superclass that each test class extends. The superclass then contains the annotated #BeforeClass and #AfterClass methods. Although not quite as clean as the above method, I think it will work for you.
As for the problem with failed tests, you can set maven.test.error.ignore so that the build continues on failed tests. This is not recommended as a continuing practice, but it should get you functioning until all of your tests pass. For more detail, see the maven surefire documentation.
A colleague of mine suggested the following: you can use a custom RunListener and implement the testRunFinished() method: http://junit.sourceforge.net/javadoc/org/junit/runner/notification/RunListener.html#testRunFinished(org.junit.runner.Result)
To register the RunListener just configure the surefire plugin as follows:
http://maven.apache.org/surefire/maven-surefire-plugin/examples/junit.html section "Using custom listeners and reporters"
This configuration should also be picked by the failsafe plugin.
This solution is great because you don't have to specify Suites, lookup test classes or any of this stuff - it lets Maven to do its magic, waiting for all tests to finish.
You can use the #ClassRule annotation in JUnit 4.9+ as I described in an answer another question.
Using annotations, you can do something like this:
import org.junit.*;
import static org.junit.Assert.*;
import java.util.*;
class SomethingUnitTest {
#BeforeClass
public static void runBeforeClass()
{
}
#AfterClass
public static void runAfterClass()
{
}
#Before
public void setUp()
{
}
#After
public void tearDown()
{
}
#Test
public void testSomethingOrOther()
{
}
}
Here, we
upgraded to JUnit 4.5,
wrote annotations to tag each test class or method which needed a working service,
wrote handlers for each annotation which contained static methods to implement the setup and teardown of the service,
extended the usual Runner to locate the annotations on tests, adding the static handler methods into the test execution chain at the appropriate points.
As for "Note: we're using maven 2 for our build. I've tried using maven's pre- & post-integration-test phases, but, if a test fails, maven stops and doesn't run post-integration-test, which is no help."
you can try the failsafe-plugin instead, I think it has the facility to ensure cleanup occurs regardless of setup or intermediate stage status
Provided that all your tests may extend a "technical" class and are in the same package, you can do a little trick :
public class AbstractTest {
private static int nbTests = listClassesIn(<package>).size();
private static int curTest = 0;
#BeforeClass
public static void incCurTest() { curTest++; }
#AfterClass
public static void closeTestSuite() {
if (curTest == nbTests) { /*cleaning*/ }
}
}
public class Test1 extends AbstractTest {
#Test
public void check() {}
}
public class Test2 extends AbstractTest {
#Test
public void check() {}
}
Be aware that this solution has a lot of drawbacks :
must execute all tests of the package
must subclass a "techincal" class
you can not use #BeforeClass and #AfterClass inside subclasses
if you execute only one test in the package, cleaning is not done
...
For information: listClassesIn() => How do you find all subclasses of a given class in Java?
As far as I know there is no mechanism for doing this in JUnit, however you could try subclassing Suite and overriding the run() method with a version that does provide hooks.
Since maven-surefire-plugin does not run Suite class first but treats suite and test classes same, so we can configure plugin as below to enable only suite classes and disable all the tests. Suite will run all the tests.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<includes>
<include>**/*Suite.java</include>
</includes>
<excludes>
<exclude>**/*Test.java</exclude>
<exclude>**/*Tests.java</exclude>
</excludes>
</configuration>
</plugin>
The only way I think then to get the functionality you want would be to do something like
import junit.framework.Test;
import junit.framework.TestResult;
import junit.framework.TestSuite;
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("TestEverything");
//$JUnit-BEGIN$
suite.addTestSuite(TestOne.class);
suite.addTestSuite(TestTwo.class);
suite.addTestSuite(TestThree.class);
//$JUnit-END$
}
public static void main(String[] args)
{
AllTests test = new AllTests();
Test testCase = test.suite();
TestResult result = new TestResult();
setUp();
testCase.run(result);
tearDown();
}
public void setUp() {}
public void tearDown() {}
}
I use something like this in eclipse, so I'm not sure how portable it is outside of that environment
If you don't want to create a suite and have to list all your test classes you can use reflection to find the number of test classes dynamically and count down in a base class #AfterClass to do the tearDown only once:
public class BaseTestClass
{
private static int testClassToRun = 0;
// Counting the classes to run so that we can do the tear down only once
static {
try {
Field field = ClassLoader.class.getDeclaredField("classes");
field.setAccessible(true);
#SuppressWarnings({ "unchecked", "rawtypes" })
Vector<Class> classes = (Vector<Class>) field.get(BlockJUnit4ClassRunner.class.getClassLoader());
for (Class<?> clazz : classes) {
if (clazz.getName().endsWith("Test")) {
testClassToRun++;
}
}
} catch (Exception ignore) {
}
}
// Setup that needs to be done only once
static {
// one time set up
}
#AfterClass
public static void baseTearDown() throws Exception
{
if (--testClassToRun == 0) {
// one time clean up
}
}
}
If you prefer to use #BeforeClass instead of the static blocks, you can also use a boolean flag to do the reflection count and test setup only once at the first call. Hope this helps someone, it took me an afternoon to figure out a better way than enumerating all classes in a suite.
Now all you need to do is extend this class for all your test classes. We already had a base class to provide some common stuff for all our tests so this was the best solution for us.
Inspiration comes from this SO answer https://stackoverflow.com/a/37488620/5930242
If you don't want to extend this class everywhere, this last SO answer might do what you want.

Categories

Resources