JUnit Tests (Integrations Tests) only on local machine [duplicate] - java

When writing code that interacts with external resources (such as using a web service or other network operation), I often structure the classes so that it can also be "stubbed" using a file or some other input method. So then I end up using the stubbed implementation to test other parts of the system and then one or two tests that specifically test calling the web service.
The problem is I don't want to be calling these external services either from Jenkins or when I run all of the tests for my project (e.g. "gradle test"). Some of the services have side effects, or may not be accessible to all developers.
Right now I just uncomment and then re-comment the #Test annotation on these particular test methods to enable and disable them. Enable it, run it manually to check it, then remember to comment it out again.
// Uncomment to test external service manually
//#Test
public void testSomethingExternal() {
Is there is a better way of doing this?
EDIT: For manual unit testing, I use Eclipse and am able to just right-click on the test method and do Run As -> JUnit test. But that doesn't work without the (uncommented) annotation.

I recommend using junit categories. See this blog for details : https://community.oracle.com/blogs/johnsmart/2010/04/25/grouping-tests-using-junit-categories-0.
Basically, you can annotate some tests as being in a special category and then you can set up a two test suites : one that runs the tests of that category and one that ignores tests in that category (but runs everything else)
#Category(IntegrationTests.class)
public class AccountIntegrationTest {
#Test
public void thisTestWillTakeSomeTime() {
...
}
#Test
public void thisTestWillTakeEvenLonger() {
....
}
}
you can even annotate individual tests"
public class AccountTest {
#Test
#Category(IntegrationTests.class)
public void thisTestWillTakeSomeTime() {
...
}
Anytime I see something manually getting turned on or off I cringe.

As far as I can see you use gradle and API for JUnit says that annotation #Ignore disables test. I will add gradle task which will add #Ignore for those tests.

If you're just wanting to disable tests for functionality that hasn't been written yet or otherwise manually disable some tests temporarily, you can use #Ignore; the tests will be skipped but still noted in the report.
If you are wanting something like Spring Profiles, where you can define rulesets for which tests get run when, you should either split up your tests into separate test cases or use a Filter.

You can use #Ignore annotation to prevent them from running automatically during test. If required, you may trigger such Ignored tests manually.
#Test
public void wantedTest() {
return checkMyFunction(10);
}
#Ignore
#Test
public void unwantedTest() {
return checkMyFunction(11);
}
In the above example, unwantedTest will be excluded.

Related

Spring Boot / JUnit, run all unit-tests for multiple profiles

I have a BaseTest class which consists of several tests. Each test shall be executed for EVERY profile I list.
I thought about using Parameterized values such as:
#RunWith(Parameterized.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
// #ActiveProfiles("h2-test") // <-- how to iterate over this?
public abstract class BaseTest {
#Autowired
private TestRepository test;
// to be used with Parameterized/Spring
private TestContextManager testContextManager;
public BaseTest(String profile) {
System.setProperty("spring.profiles.active", profile);
// TODO what now?
}
#Parameterized.Parameters
public static Collection<Object[]> data() {
Collection<Object[]> params = new ArrayList<>();
params.add(new Object[] {"h2-test" });
params.add(new Object[] {"mysql-test" });
return params;
}
#Before
public void setUp() throws Exception {
this.testContextManager = new TestContextManager(getClass());
this.testContextManager.prepareTestInstance(this);
// maybe I can spinup Spring here with my profile?
}
#Test
public void testRepository() {
Assert.assertTrue(test.exists("foo"))
}
How would I tell Spring to run each test with these different profiles? In fact, each profile will talk to different datasources (in-memory h2, external mysql, external oracle, ..) so my repository/datasource has to be reinitialized.
I know that I can specify #ActiveProfiles(...) and I can even extend from BaseTest and override the ActiveProfile annotation. Although this will work, I only show a portion of my test-suite. Lots of my test-classes extend from BaseTest and I don't want to create several different profile-stubs for each class. Currently working, but ugly solution:
BaseTest (#ActiveProfiles("mysql"))
FooClassMySQL(annotation from BaseTest)
FooClassH2(#ActiveProfiles("h2"))
BarClassMySQL(annotation from BaseTest)
BarClassH2(#ActiveProfiles("h2"))
Thanks
For what it's worth:
My use case was to run a specific test class for multiple spring profiles, this is how I achieved it:
#SpringBootTest
abstract class BaseTest {
#Test void doSomeTest() {... ARRANGE-ACT-ASSERT ...}
}
#ActiveProfiles("NextGen")
class NextGenTest extends BaseTest {}
#ActiveProfiles("Legacy")
class LegacyTest extends BaseTest {}
If you use Maven you can actually specify active profile from command line (or env variable if needed):
mvn clean test -Dspring.profiles.active=h2-test
The approach with parameterized test may not work in this case, because profile has to be specified before Spring boots up its context. In this case when you run parameterized integration test the context will be already booted up before test runner starts running your test. Also JUnit's parameterized tests were invented for other reasons (running unit tests with different data series).
EDIT: Also one more thing - when you decide to use #RunWith(Parameterized.class) you wont be able to use different runner. In many cases (if not all if it comes to integration testing) you want to specify different runner, like SpringRunner.class - with parameterized test you wont be able to do it.
Spring profiles are not designed to work in this way.
In your case, each profile uses a specific datasource.
So each one requires a Spring Boot load to run tests with the expected datasource.
In fact, what you want to do is like making as many Maven build as Spring profiles that you want to test.
Besides, builds in local env should be as fast as possible.
Multiplying automated tests execution by DBMS implementation that requires a Spring Boot reload for each one will not help.
You should not need to specify #ActiveProfiles .
It looks rather like a task for a Continuous Integration tool where you could define a job that executes (sequentially or parallely) each Maven build by specifying a specific Spring Boot profile :
mvn clean test -Dspring.profiles.active=h2
mvn clean test -Dspring.profiles.active=mysql
etc...
You can also try to perform it in local by writing a script that performs the execution of the maven builds.
But as said, it will slowdown your local build and also complex it.

Model Based Testing android

I have generated test cases that I need to execute. I have written my methods of the tests independent of each other and writing scripts to execute these methods via the adb is not helping since they dont execute in order of the sequence given it.
I would like to know a preferred approach to take ?
Or how I can automate these multiple tests via the adb.
I have realized all most out there tend to use the adb commands under their codes so dont know if there is a tool that may be of help. I am open to that as well
Thank you
I think there's a problem with your test case structure.
Test cases should be independent of each other and that is not something that is only encouraged but often a necessity to ensure integrity of your tests.
If you have dependent actions then they need to be bundled in the same test case or you need to look at dependency injection/mocks.
That being said, JUnit4 has a #FixMethodOrder annotation which you can add to run the tests in order.
import org.junit.runners.MethodSorters;
import org.junit.FixMethodOrder;
import org.junit.Test;
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {
#Test
public void firstTest() {
System.out.println("first");
}
#Test
public void secondTest() {
System.out.println("second");
}
}

getting TestNG to treat class variables like JUnit with Guice

I am trying to setup TestNG so that it gives me new instances of my class variable for each test (basically like JUnit). I need this as I intend to parallelize my tests at the method level. I have been experimenting with both standalone Guice and the built in Guice functionality that TestNG provides to try to accomplish this but I have had no luck. I know that I can use ThreadLocal, but calling .get() for every variable in the test is pretty unappealing. I am weary of using GuiceBerry as it does not really have a lot of updates/activity and it's last release is not even acquirable via Maven. I am pretty set on TestNG as for all the inconvenience this is causing me it still does a lot of great things. I am open to things other tools though to accomplish my goal. Basically I want things setup so the below tests would work consistently. Any help would be greatly appreciated.
// just has a variable thats a class called child with a simple string variable
// with a value of "original
Parent p;
#Test
public void sometest1(){
p.child.value = "Altered";
Assert.assertTrue(p.child.value.equals("Altered"));
}
#Test
public void sometest2(){
Assert.assertTrue(p.child.value.equals("original"));
}
TestNG doesn't create a new instance for each test. If you want such a behavior than I recommend creating separate test classes. e.g.:
public class SomeTest1 {
Parent p;
#Test
public void something(){
p.child.value = "Altered";
Assert.assertTrue(p.child.value.equals("Altered"));
}
}
public class SomeTest2 {
Parent p;
#Test
public void something(){
Assert.assertTrue(p.child.value.equals("original"));
}
}
Note that TestNG can run JUnit 3 and JUnit 4 tests (you might maintain a mixed suite depending on the style you want to use in a given test class).

Testing different Java Versions in Junit

is there a way to specify the JVM version in a junit test, when multiple java types are available on an OS ?
I'd like to do something like this:
#JVM=1.5
public void test1(){
run();
}
#JVM=1.7
public void test2(){
run();
}
etc..
No, you'll have to run the JUnit tests multiple times with multiple VMs. You can then use Assume to only run the tests for the correct VM:
public void test1(){
// not compiled or tested
Assume.assumeThat(System.getProperty("java.version"), CoreMatchers.startsWith("1.5"));
run();
}
public void test2(){
Assume.assumeThat(System.getProperty("java.version"), CoreMatchers.startsWith("1.7"));
run();
}
Please note that I haven't compiled this, so there may be errors. Then, in your build tool, run these tests twice in two different VMs.
On JUnit 5, you can use EnabledOnJre and DisabledOnJre annotations.
#EnabledOnJre(JRE.JAVA_8)
void testMyMethodInJava8() {
...
}
#DisabledOnJre(JRE.JAVA_8)
void testMyMethodInOtherVersions() {
...
}
You can also apply these to a whole test class:
#EnabledOnJre(JRE.JAVA_11)
public class MyClassTest {
...
}
You still need to run the test suite separately for each JVM, but this allows you to skip the tests that will not work in one or the other.
JUnit test cases are just a bunch of Java classes, not a standalone program. So they would still be confined within the same JVM. AFAIK there is no simple way to do what you intend to do. What you can do is separate the test cases into test suites for each java version you want to test for. Then change the java version in the project settings and run the appropriate test suites.
Also there is a junit.jvm property, but I am not sure if you can change it mid-execution. Have you taken a look at it?

Unrooted Tests

When running all my tests in Eclipse (Eclipse 3.4 'Ganymede'), one test is listed under "Unrooted Tests". I'm using Junit 3.8 and this particular test extends TestCase. I do not see any difference between this test and the other tests. I don't remember seeing this occur in Eclipse 3.3 (Europa).
Clarification:
We haven't moved to JUnit 4.0 yet, so we are not using annotations. I also googled and it seemed like most people were having issues with JUnit 4, but I did not see any solutions. At this point the test passes both locally and in CruiseControl so I'm not overly concerned, but curious.
When I first saw this, though, it was on a failing test that only failed when run with other tests. This led me down the rabbit hole looking for a solution to the "Unrooted" issue that I never found. Eventually I found the culprit in another test that was not properly tearing down.
I agree, it does seem like an Eclipse issue.
Finally I found the solution. The problem is that you are not defining your test cases using annotations but are still doing it the "old way". As soon as you convert over to using annotations you will be able to run one test at a time again.
Here is an example of what a basic test should now look like using annotations:
import static org.junit.Assert.*; // Notice the use of "static" here
import org.junit.Before;
import org.junit.Test;
public class MyTests { // Notice we don't extent TestCases anymore
#Before
public void setUp() { // Note: It is not required to call this setUp()
// ...
}
#Test
public void doSomeTest() { // Note: method need not be called "testXXX"
// ...
assertTrue(1 == 1);
}
}
I was getting the "unrooted tests" error message as well and it went away magically. I believe it was due to the fact that I was using Eclipse with a Maven project. When I added a new method to my Test class and gave it the #Test annotation, it began getting the error message when I tried to run that one method using the "Run as Junit test" menu option; however, once I ran a maven build the unrooted tests message disappeared and I believe that is the solution to the problem in the future.
Run a maven build because it will refresh the class that JUnit is using.
If your class extends TestCase somewhere in its hierarchy, you have to use the JUnit 3 test runner listed in the drop down under run configurations. Using the JUnit 4 runner (the default I believe) causes that unrooted test phenomenon to occur.
I got this error because I renamed my test method and then tried to run the test in Eclipse by clicking on the same run configuration - referring to the old method which now didn't exist.
We solved the problem by making sure our test project was built. We had an issue in the build path which would not allow our test class to be compiled. Once we resolved the build path issue, the test compiled and the "new" method was able to be run. So we can assume that "Unrooted" tests also mean that they don't exist in the compiled binary.
I've never seen this -- but as far as I can tell from skimming Google for a few minutes, this appears as though it could be a bug in Eclipse rather than a problem with your test. You don't have the #Test annotation on the test, I assume? Can you blow the test away and recreate it, and if so do you get the same error?
Another scenario that causes this problem was me blindly copy/pasting a method that requires a parameter. i.e.
import org.junit.Test;
public class MyTest {
#Test
public void someMethod(String param) {
// stuff
}
}
You have a few simple solutions:
define the variable in the specific test method
add it as an instance variable to the test class
create a setup method and annotate it with #Before
For me, it was due to the project got build path issues. My maven dependencies configuration needs to be updated.
I had that problem and putting one "#Test" before the test method solved it!
like this:
#Test
public void testOne() { // ...
assertTrue(1 == 1);
}
These are the two scenarios that the Unrooted errors show up.
If you have missed the annotation #Test before the test.
#Test
public void foo(){
}
If it is a Gwt project and when two mock of the same object are defined. Lets say there is one class Class A and
#GwtMock
private A atest;
#GwtMock
private A a;
Then this will also show a Unrooted test error.
One other thing you can try is to upgrade your version of JUnit to at least 4.12.
I was experiencing this problem for a while with a class that extended one that used #RunWith(Parameterized.class).
After a while, and I'm sorry that I don't know precisely what I did to cause this, the 'Unrooted Tests' message went away, but the test still didn't run correctly. The constructor that should have accepted arguments from the #Parameters method was never getting called; execution jumped straight from #BeforeClass to #AfterClass.
The fix for that problem was to upgrade JUnit from the 4.8.1 it was using, to the latest (4.12). So maybe that could help someone else in the future.
I had the same problem with
java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
you need the jar hamcrest.
same question 14539072: java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
I could the fix the issue by shifting from TestRunner ver 4.0 to 3 in run configurations for the individual test method.
Do not extend junit.framework.TestCase in your test class with junit1.4 and this should solve the problem
You are using Hamcrest? or another library to help in your test?. You are not using
import static org.junit.Assert.*;
Check if in your test you use:
import static org.hamcrest.MatcherAssert.assertThat;
or other assert isnĀ“t JUnit assert.
It turned out to be that my build path had some error...some jars were missing.
I reconfigured build path and it worked!
For me the problem was, that an exception was thrown in the #BeforeClass or #AfterClass methods. This will also cause tests to be categorized as unrooted.
I got this error with the test method name as "test"
#Test
public void test() {
// ... assertTrue(1 == 1);
}
I renamed the method and it worked
I ran into this problem by not also declaring the test to be static.
Maybe it's just a logical confusion about the goal of the method. Let's remember:
E.g. correct tagged test method:
#Test
#Transactional
#Rollback(true)
public void testInsertCustomer() {
(...)
}
-With Eclipse Junit plugin, You can run that test method using context menu over the method (E.g. at package explorer expanding the class and methods and selecting "testInsertCustomer()" method and from that item selecting "Run as >> JUnit test").
If you forgot "#Test" tag, or simply the method is not a test, but a (private or not) common method for using as utility for the other tests (e.g. "private fillCustomerObject()"), then the method does not require "#Test" tag, and simply you can not run it as a JUnit test!
It's easy that you could create a utility method and later you forgot the real goal of that method, so if you try to run it as a test, JUnit will shout "Unrooted Tests".
For me this problem was created by a real-time exception thrown in the #AfterClass method (take a look here for documentation):
Basically all the test methods succeeded but at the end of the class this method was failing. Therefore all the tests seems fine but there was on my Eclipse an additional "unrooted test" failed.
I got these errors for a maven project. I rebuild the project with mvn clean install.And the issue was solved
It actually told me there is a test with annotation: #RunWith(MockitoJUnitRunner.class)

Categories