I'm having trouble understanding why all those processors pass the test but Behavior does not:
package com.example;
import org.junit.Test;
import io.reactivex.Flowable;
import io.reactivex.processors.*;
public class ProcessorTest {
private static Flowable<String> justFoo() {
return Flowable.just("foo");
}
private static FlowableProcessor<String> subscribeToFoo(
FlowableProcessor<String> processor) {
justFoo().subscribe(processor);
return processor;
}
#Test public void flowable() { // pass
justFoo().test().assertValue("foo");
}
#Test public void async() { // pass
subscribeToFoo(AsyncProcessor.create()).test().assertValue("foo");
}
#Test public void replay() { // pass
subscribeToFoo(ReplayProcessor.create()).test().assertValue("foo");
}
#Test public void unicast() { // pass
subscribeToFoo(UnicastProcessor.create()).test().assertValue("foo");
}
#Test public void behaviorFail() { // fail
subscribeToFoo(BehaviorProcessor.create()).test().assertValue("foo");
}
#Test public void behaviorPassing() { // pass
subscribeToFoo(BehaviorProcessor.create())
.test()
.assertNoValues()
.assertSubscribed()
.assertComplete()
.assertNoErrors()
.assertNoTimeout()
.assertTerminated();
}
}
The docs say that BehaviorProcessor is a:
Processor that emits the most recent item it has observed and all subsequent observed items to each subscribed Subscriber.
So in my understanding it should pass the behaviorFail test, not the behaviorPassing. How come is that?
How would I write a valid test, to know that a BehaviorProcessor emitted a certain value?
Getting rid of the terminal event passed to the processor would help:
#Test public void behavior() {
final BehaviorProcessor<String> processor = BehaviorProcessor.create();
justFoo().concatWith(Flowable.never()).subscribe(processor);
processor.test().assertValue("foo");
}
I have class that has 3 methods: insert, update and delete from the db.
In order to test it in the insert test method I need to use the insert method and after I insert i need to delete what I inserted, but in order to delete I should use the delete method that I also want to test so it didn't make sense to me that I need to use them and also test them.
I hope you understand my problem. Thanks in advance!
You must decide what you want to test. That was you describe, it is an integration test. By a “real” unitTest, you test only your method, and not the System method and not the database.
If you want a unitTest, you have several options. For Example, you work with interfaces and catch your statement before it comes to the database.
Edit 1 - one possibility to implement unit test with interfaces:
You need one interface that implements the method these go to the backend system:
public interface IDatabase{
public returnValue insert(yourParam);
public int update(yourParam);
}
Then you implement your method with the real functions in a class:
public class Database implements IDatabase {
#Override
public returnValue insert(yourParam) {
// do something
return null;
}
#Override
public int update(yourParam){
// do something
return 0;
}
}
This class you call in the main class:
/**
* The real class to do what you want to do.
*/
public class RealClass {
private IDatabase dbInstance = null;
private IDatabase getDbInstance() {
if (dbInstance == null) {
dbInstance = new Database();
}
return dbInstance;
}
protected void setDbInstance(IDatabase dataBase) {
dbInstance = dataBase;
}
public static void main(String[] args) {
getDbInstance().insert(yourParam);
}
}
For the unit test you implement the interface again:
public class UnitTest implements IDatabase {
#Override
public returnValue insert(yourParam) {
// Here can you test your statement and manipulate the return value
return null;
}
#Override
public int update(yourParam){
if (yourParam.containsValue(value1)) {
assertEquals("yourStatement", yourParam);
return 1;
}else if (yourParam.containsValue(value2)) {
assertEquals("yourStatement2", yourParam);
return 5;
}else{
assertTrue(false,"unknown Statement")
}
}
#Test
public void yourTest(){
RealClass.setDbInstance(this);
//Test something
}
}
This is time-consuming to implement, but with this, you are independent from the backend system and you can call the unittest every time without a database.
By default, the order of test methods is not warrantied in JUnit. Nevertheless, as of JUnit 4.11, you can order by the test name, as follows:
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class Test1 {
#Test
public void aInsert() {
System.out.println("first INSERT");
}
#Test
public void bUpdate() throws Exception {
System.out.println("second UPDATE");
}
#Test
public void cDelete() throws Exception {
System.out.println("third DELETE");
}
}
We are running Sonarqube 5.6.1 with the Java Plugin 4.1 and having some troubles using the Sonar rule S2699 (Test should include assertions).
Using this example test class
import mypackage.Citit1543Dummy;
import mypackage.Citit1543OtherDummy;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isIn;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.core.IsNot.not;
import static org.mockito.Matchers.notNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.junit.Assert.assertThat;
public class Citit1543Test {
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test1() {
assert true;
}
#Test
public void test2() {
Assert.assertTrue(1 > (2-3));
}
#Test
public void test3() {
Assert.assertFalse(1 > (100-1));
}
#Test
public void test4() {
Assert.assertThat("test", 1, is(1));
}
#Test
public void test5() {
Assert.assertArrayEquals(new String[0], new String[0]);
}
#Test
public void test6() {
Assert.assertEquals(1 > 0, true);
}
#Test
public void test7() { // asserts in another method
test7asserts(1, 1);
}
private void test7asserts(int a, int b) {
Assert.assertTrue(a == b);
}
#Test
public void test8() {
test8asserts(1, 2);
}
private void test8asserts(int a, int b) {
Assert.assertNotSame(a, b);
}
#Test
public void test9() {
Citit1543Dummy dummy = new Citit1543Dummy();
dummy.otherDummy = mock(Citit1543OtherDummy.class);
dummy.doSomething();
verify(dummy.otherDummy, times(1)).doSomething();
}
#Test
public void test10() {
Citit1543Dummy dummy = new Citit1543Dummy();
dummy.otherDummy = mock(Citit1543OtherDummy.class);
dummy.doSomething();
test10verifies(dummy.otherDummy);
}
private void test10verifies(Citit1543OtherDummy otherDummy) {
verify(otherDummy, times(1)).doSomething();
}
#Test
public void test11() {
Assert.assertThat("test", "", not(1));
}
#Test
public void test12() {
Assert.assertThat("test", 1, lessThan(2));
}
#Test
public void test13() {
Long[] arr = new Long[] { 1L, 2L, 3L, 4L };
assertThat("Just testing", arr, is(new Long[] {
1L, 2L, 3L, 4L
}));
}
}
our Sonarqube instance flags the test cases test1 (assert statement not recognized), test7 (assert statements in another method), test8 (same) , test10 (Mockitos verify in another method), test11 and test13 as methods without assertions. I'm pretty sure that there are a lot more methods which aren't recognized (yes, unfortunately we use a bunch of different mocking/testing framework across our projects).
For now, we started to //NOSONAR whenever one of the asserts/verifies aren't recognized.
Is there an easy way to include these methods to be recognized as valid asserts?
Many of your stated issues are known and indeed (in some form of another) marked as FP:
test1: The current flow analysis ignores assert statements. See this post over at the groups.
The cases test7, test8 and test10 are related to the lack of not having cross-procedural analysis: They are valid cases but the current flow doesn't know that (ex.) test7assert is a valid assert statement for another method. See this post over at the groups.
Your other cases also produce false positives in the tests of S2699. I'd expect that once a SonarSource dev reads this topic that they'll create a ticket to resolve the cases in test11/13. But as I'm not a dev of them I can't guarantee that of course.
As to :
Is there an easy way to include these methods to be recognized as valid asserts?
No, the valid assertions are defined within the code of S2699 and are not a parameter. Some of your cases will require a more complex flow analysis whilst the last couple just seem to boil down to some missing definitions or too strict definitions, but I didn't deep-dive into the reasons why they produce FPs.
Instead of constantly creating identical debug configuraitons for my test cases, I would like to be able to simply save a few arguments common across all my Junit tests, right click on a specific test, then run that single run config. IE I would like a single debug configuration that can take as an argument the current selected test case instead of requiring me to manually specify it every time in the JUnit run configuration. My only options in the dialog appear to be either to specify a single test class or run all the tests in the project. As a result, Eclipse is littered with dozens of run configurations for all my test cases.
Instead of specifying a specific test class, I'd like it to specify a variable like ${container_loc} or ${resource_loc} for the class to run as in this question. Is there a variable in Eclipse that specifies the current selected Java class that I could place in the test class field in the dialog?
A specific example where this is useful is when running the Lucene unit tests. There's lots of arguments you can specify to customize the tests, some of which like -ea are required. Everytime I want to test a specific test case in Lucene in Eclipse, I have to manually setup these variables in the Eclipse debug config dialog :-/.
Have you looked at Parameterized Tests in JUnit? Here is an example:
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
#RunWith(Parameterized.class)
public class ParamTest {
#Parameters(name = "{index}: fib({0})={1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] {
{ 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 }
});
}
private int input;
private int expected;
public ParamTest(int input, int expected) {
this.input = input;
this.expected = expected;
}
#Test
public void test() {
Assert.assertEquals(expected, input);
}
}
If you just want to run one test at a time you can use private variables as in:
public class MultipleTest {
private int x;
private int y;
public void test1(){
Assert.assertEquals(x, y);
}
public void test2(){
Assert.assertTrue(x >y);
}
public void args1(){
x=10; y=1;
}
public void args2(){
x=1;y=1;
}
public void args3(){
x=1;y=10;
}
#Test
public void testArgs11(){
args1();
test1();
}
#Test
public void testArgs21(){
args2();
test1();
}
#Test
public void testArgs31(){
args3();
test1();
}
#Test
public void testArgs12(){
args1();
test2();
}
#Test
public void testArgs22(){
args2();
test2();
}
#Test
public void testArgs32(){
args3();
test2();
}
}
In JUnit 3, I could get the name of the currently running test like this:
public class MyTest extends TestCase
{
public void testSomething()
{
System.out.println("Current test is " + getName());
...
}
}
which would print "Current test is testSomething".
Is there any out-of-the-box or simple way to do this in JUnit 4?
Background: Obviously, I don't want to just print the name of the test. I want to load test-specific data that is stored in a resource with the same name as the test. You know, convention over configuration and all that.
JUnit 4.7 added this feature it seems using TestName-Rule. Looks like this will get you the method name:
import org.junit.Rule;
public class NameRuleTest {
#Rule public TestName name = new TestName();
#Test public void testA() {
assertEquals("testA", name.getMethodName());
}
#Test public void testB() {
assertEquals("testB", name.getMethodName());
}
}
JUnit 4.9.x and higher
Since JUnit 4.9, the TestWatchman class has been deprecated in favour of the TestWatcher class, which has invocation:
#Rule
public TestRule watcher = new TestWatcher() {
protected void starting(Description description) {
System.out.println("Starting test: " + description.getMethodName());
}
};
Note: The containing class must be declared public.
JUnit 4.7.x - 4.8.x
The following approach will print method names for all tests in a class:
#Rule
public MethodRule watchman = new TestWatchman() {
public void starting(FrameworkMethod method) {
System.out.println("Starting test: " + method.getName());
}
};
JUnit 5 and higher
In JUnit 5 you can inject TestInfo which simplifies test metadata injection to test methods. For example:
#Test
#DisplayName("This is my test")
#Tag("It is my tag")
void test1(TestInfo testInfo) {
assertEquals("This is my test", testInfo.getDisplayName());
assertTrue(testInfo.getTags().contains("It is my tag"));
}
See more: JUnit 5 User guide, TestInfo javadoc.
Try this instead:
public class MyTest {
#Rule
public TestName testName = new TestName();
#Rule
public TestWatcher testWatcher = new TestWatcher() {
#Override
protected void starting(final Description description) {
String methodName = description.getMethodName();
String className = description.getClassName();
className = className.substring(className.lastIndexOf('.') + 1);
System.err.println("Starting JUnit-test: " + className + " " + methodName);
}
};
#Test
public void testA() {
assertEquals("testA", testName.getMethodName());
}
#Test
public void testB() {
assertEquals("testB", testName.getMethodName());
}
}
The output looks like this:
Starting JUnit-test: MyTest testA
Starting JUnit-test: MyTest testB
NOTE: This DOES NOT work if your test is a subclass of TestCase! The test runs but the #Rule code just never runs.
Consider using SLF4J (Simple Logging Facade for Java) provides some neat improvements using parameterized messages. Combining SLF4J with JUnit 4 rule implementations can provide more efficient test class logging techniques.
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.junit.rules.TestWatchman;
import org.junit.runners.model.FrameworkMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoggingTest {
#Rule public MethodRule watchman = new TestWatchman() {
public void starting(FrameworkMethod method) {
logger.info("{} being run...", method.getName());
}
};
final Logger logger =
LoggerFactory.getLogger(LoggingTest.class);
#Test
public void testA() {
}
#Test
public void testB() {
}
}
A convoluted way is to create your own Runner by subclassing org.junit.runners.BlockJUnit4ClassRunner.
You can then do something like this:
public class NameAwareRunner extends BlockJUnit4ClassRunner {
public NameAwareRunner(Class<?> aClass) throws InitializationError {
super(aClass);
}
#Override
protected Statement methodBlock(FrameworkMethod frameworkMethod) {
System.err.println(frameworkMethod.getName());
return super.methodBlock(frameworkMethod);
}
}
Then for each test class, you'll need to add a #RunWith(NameAwareRunner.class) annotation. Alternatively, you could put that annotation on a Test superclass if you don't want to remember it every time. This, of course, limits your selection of runners but that may be acceptable.
Also, it may take a little bit of kung fu to get the current test name out of the Runner and into your framework, but this at least gets you the name.
JUnit 4 does not have any out-of-the-box mechanism for a test case to get it’s own name (including during setup and teardown).
String testName = null;
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
for (int i = trace.length - 1; i > 0; --i) {
StackTraceElement ste = trace[i];
try {
Class<?> cls = Class.forName(ste.getClassName());
Method method = cls.getDeclaredMethod(ste.getMethodName());
Test annotation = method.getAnnotation(Test.class);
if (annotation != null) {
testName = ste.getClassName() + "." + ste.getMethodName();
break;
}
} catch (ClassNotFoundException e) {
} catch (NoSuchMethodException e) {
} catch (SecurityException e) {
}
}
Based on the previous comment and further considering I created an extension of TestWather which you can use in your JUnit test methods with this:
public class ImportUtilsTest {
private static final Logger LOGGER = Logger.getLogger(ImportUtilsTest.class);
#Rule
public TestWatcher testWatcher = new JUnitHelper(LOGGER);
#Test
public test1(){
...
}
}
The test helper class is the next:
public class JUnitHelper extends TestWatcher {
private Logger LOGGER;
public JUnitHelper(Logger LOGGER) {
this.LOGGER = LOGGER;
}
#Override
protected void starting(final Description description) {
LOGGER.info("STARTED " + description.getMethodName());
}
#Override
protected void succeeded(Description description) {
LOGGER.info("SUCCESSFUL " + description.getMethodName());
}
#Override
protected void failed(Throwable e, Description description) {
LOGGER.error("FAILURE " + description.getMethodName());
}
}
Enjoy!
In JUnit 5 TestInfo acts as a drop-in replacement for the TestName rule from JUnit 4.
From the documentation :
TestInfo is used to inject information about the current test or
container into to #Test, #RepeatedTest, #ParameterizedTest,
#TestFactory, #BeforeEach, #AfterEach, #BeforeAll, and #AfterAll
methods.
To retrieve the method name of the current executed test, you have two options : String TestInfo.getDisplayName() and
Method TestInfo.getTestMethod().
To retrieve only the name of the current test method TestInfo.getDisplayName() may not be enough as the test method default display name is methodName(TypeArg1, TypeArg2, ... TypeArg3).
Duplicating method names in #DisplayName("..") is not necessary a good idea.
As alternative you could use
TestInfo.getTestMethod() that returns a Optional<Method> object.
If the retrieval method is used inside a test method, you don't even need to test the Optional wrapped value.
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.Test;
#Test
void doThat(TestInfo testInfo) throws Exception {
Assertions.assertEquals("doThat(TestInfo)",testInfo.getDisplayName());
Assertions.assertEquals("doThat",testInfo.getTestMethod().get().getName());
}
JUnit 5 via ExtensionContext
Advantage:
You get to have the added functionalities of ExtensionContext by overriding afterEach(ExtensionContext context).
public abstract class BaseTest {
protected WebDriver driver;
#RegisterExtension
AfterEachExtension afterEachExtension = new AfterEachExtension();
#BeforeEach
public void beforeEach() {
// Initialise driver
}
#AfterEach
public void afterEach() {
afterEachExtension.setDriver(driver);
}
}
public class AfterEachExtension implements AfterEachCallback {
private WebDriver driver;
public void setDriver(WebDriver driver) {
this.driver = driver;
}
#Override
public void afterEach(ExtensionContext context) {
String testMethodName = context.getTestMethod().orElseThrow().getName();
// Attach test steps, attach scsreenshots on failure only, etc.
driver.quit();
}
}
#ClassRule
public static TestRule watchman = new TestWatcher() {
#Override
protected void starting( final Description description ) {
String mN = description.getMethodName();
if ( mN == null ) {
mN = "setUpBeforeClass..";
}
final String s = StringTools.toString( "starting..JUnit-Test: %s.%s", description.getClassName(), mN );
System.err.println( s );
}
};
I usually use something like this:
/** Returns text with test method name
#param offset index of method on call stack to print, 1 for a caller of this method.
*/
static String getName(int offset)
{
Throwable t = new Throwable();
t.fillInStackTrace();
return
t.getStackTrace()[offset].getMethodName()+":"+t.getStackTrace()[offset].getLineNumber();
};
This is exactly what Exception do use when printing stack trace.
Depending on the exact context You may have to figure out correct offset value. It is crude and primitive tough and is not using any fancy modern futures.
I'd suggest you decouple the test method name from your test data set. I would model a DataLoaderFactory class which loads/caches the sets of test data from your resources, and then in your test case cam call some interface method which returns a set of test data for the test case. Having the test data tied to the test method name assumes the test data can only be used once, where in most case i'd suggest that the same test data in uses in multiple tests to verify various aspects of your business logic.
You can achieve this using Slf4j and TestWatcher
private static Logger _log = LoggerFactory.getLogger(SampleTest.class.getName());
#Rule
public TestWatcher watchman = new TestWatcher() {
#Override
public void starting(final Description method) {
_log.info("being run..." + method.getMethodName());
}
};
I have a Junit4 test class that extends TestCase so the example with #Rule didn't work (as mentioned in other answers).
However, if your class extends TestCase you can use getName() to get the current test name so this works:
#Before
public void setUp() {
System.out.println("Start test: " + getName());
}
#After
public void tearDown() {
System.out.println("Finish test: " + getName());
}
A more simpler way is to put this logic in setUp() and tearDown() methods.
Refer below code for better clarity,
import java.lang.reflect.Method;
#BeforeMethod
void setUp(Method method) {
log.info("###############################################");
log.info("Running Test: {}", method.getName());
}
#AfterMethod
void tearDown(Method method) {
log.info("Finished Test: {}", method.getName());
log.info("###############################################");
}
#Test
public void testMethodName() {
// Method logic implementation...
}
Here is the output of above test execution,
#############################################################
Running Test: testMethodName
// Logs related to method execution...
Finished Test: testMethodName
#############################################################