picocli: why does this JUnit test fail? - java

Test won't run correctly trying to run a JUnit test errors
package picocli;
import picocli.CommandLine.Option;
public class ComparatorRunnerConfig {
#Option(names = {"-rc", "--report-class"}, required = false,
description = "define report")
private String report;
public String getReport() {
return report;
}
}
My JUnit test:
package picocli;
import static org.junit.Assert.*;
import org.junit.Test;
public class ConfigurationTest {
#Test
public void testBasicConfigOptions() {
String args = "-rc BlahBlah";
ComparatorRunnerConfig mfc = new ComparatorRunnerConfig();
new CommandLine(mfc).parse(args);
String myTestValue = mfc.getReport();
assertEquals(myTestValue, "BlahBlah");
}
}
Test fails.

The problem is that the test has a subtle bug: the intention is to pass two arguments: the option "-rc" and its option parameter "BlahBlah", but what the test actually does is pass a single argument "-rc BlahBlah" with an embedded space.
Picocli will not be able to match this input and will throw an exception (probably the error message says something like “unknown option -rc BlahBlah”, but I’m away from my pc now, so cannot verify).
The solution is to change the test to either this:
String[] args = "-rc BlahBlah".split(" ");
or this:
String[] args = new String[] {"-rc", "BlahBlah"};
This bug in the test is actually a fairly common mistake and I’ve made this mistake myself a few times. :-)
As a side-note: you can use picocli’s tracing feature to help with troubleshooting issues like this, by setting system property -Dpicocli.trace=DEBUG.

Related

java.lang.RuntimeException: Stub! in Android with Mockito

I have been looking on Google for this error, and most of the answers I have found is to move junit dependence, to the top. Or use another mocking framework. I already moved the dependence and still fails, and the whole project uses mockito and powermock.
This is in resume, the code.
package co.pack.session;
import com.google.gson.JsonObject;
import org.junit.Test;
import co.pack.Session.Organization;
import static org.junit.Assert.assertEquals;
public class TestOrganization {
#Test
public void testLoadJson() {
JsonObject json = new JsonObject();
json.addProperty("theme_color", "red");
Organization organization = new Organization();
organization.loadFromJson(json);
assertEquals("red", Organization.getThemeColor());
}
}
Implementation
public static void loadFromJson(JsonObject json) {
Organization.name = json.has("name") ? json.get("name").getAsString() : "";
Organization.image = json.has("image") ? json.get("image").getAsString() : "";
printActualOrganization();
}
private static void printActualOrganization() {
Log.i(TAG, "_name_ " + name);
Log.i(TAG, "_image_ " + image);
}
It fails on a Log line
Log.i(TAG, "_name_ " + name);
And got this
java.lang.RuntimeException: Stub!
at android.util.Log.i(Log.java:9)
at co.mobico.Session.Organization.loadJson(Organization.java:50)
at co.mobico.session.TestOrganization.testLoadJson(TestOrganization.java:28)
Log lines, never causes any error on my test, I don't know what is happening in this case.
You can try add the following options to your app build.gradle.
android {
testOptions {
unitTests.returnDefaultValues = true
}
}
This should prevent you from getting this RuntimeException, because in this case the Android-Methods will return default values. Be aware that this might raise other problems, e.g. when using TextUtils.equals(...).
Basically I agree with the strategy to mock every dependency of your unit under test, but you can use the return values as a kind of workaround.
The problem is that you call a method directly on a mock.
You usually don't do that.
Usually you create a normal instance of your class under test (cut) and mocks for the dependencies it communicates with:
#Test public void exampleWithMocks(){
// arrange
DataTransferObject dto = new DataTransferObject();
dto.setSomeProperty(SOME_PRIMITIVE_VALUE_OR_STRING);
SomeServiceTheCutDependsOn dependency = mock( SomeServiceTheCutDependsOn.class);
ClassUnderTest cut = new ClassUnderTest(dependency);
// act
Object result = cut.doSomethingWith(dto);
// assert
assertThat(result,notNullValue());
verify(dependency).expectedMethodCall(dto);
}

Java Unit testing path matching

I am trying to understand Unit testing and how the correct classes are being fetched on test time,
I'm having a hard time understanding exactly what is going on behind the scenes and how safe/correct my usages for this are.
This is a very simple example of what i am trying to do, i wrote it here inline so it probably contains some errors, please try to ignore them, as stupid as they may be.
A very simple project directory:
ba/src/main/java/utils/BaUtils.java
ba/test/main/java/utils/BaUtilsTest.java
notBa/src/main/java/im/BaObj.java
BaUtils.java code:
package com.ba.utils;
import notBa.im.BaObj;
public class BaUtils{
public String doSomething(BaObj obj){
obj.doSomething();
}
}
I would like to test BaUtils wihtout actually calling doSomething, and i can't change anything on BaObj class or notBa package. I know that i can (by 'can' i mean it will work) add a new java file to 'ba' project (ba/test/java/notBa/main/java/im/BaObj.java) that will have the same package as the original BaObj, and at runtime the test will import this one instead of the real one, so BaUtils code is tested but BaObj code is not excecuted.
that should look something like like :
package notBa.im.Baobj
public class BaObj{
public void doSomething(){
System.out.println("Did something");
}
}
My questions are (And thank you for reaching this far):
How does this work (Reading references would be great).
Is this kind of test building considered 'good' or 'safe' ?
Thanks!
The solution is to use a mocking framework (I for myself like Mockito).
The test would look like this:
class BlaUtilTes{
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Mock
Blaobj blaobj;
#Test
public void doSomething_WithMockedBlaobj_callsDosomethingOnBlaobj(){
// arrange
BlaUtil blaUtil= new BlaUtil();
// act
blaUtil.doSomething(blaobj);
// assert
Mockito.verify(blaobj).doSomething();
}
}
find more information here http://www.vogella.com/tutorials/Mockito/article.html#testing-with-mock-objects
Your BaUtilsTest class should look like this.. I have used mockito for for mocking external dependencies. Also I changed the method return type to String for easy understanding.
#RunWith(MockitoJUnitRunner.class)
class BaUtilsTest {
BaUtils util;
#Mock
BaObj mockBaObj;
#Before
public void setup() {
util = new BaUtils();
}
#Test
public void testDoSomething() {
Mockito.when(mockBaObj.doSomething()).thenReturn("did the work using mock");
String result = util.doSomething(mockBaObj);
Assert.assertEquals("did the work using mock", result);
}
}

Misplaced argument matcher detected here. You cannot use argument matchers outside of verification or stubbing in Mockito

Out of the following two test cases in BundleProcessorTest.java, i am getting below exception, although, my first test case passes successfully.
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
-> at bundle.test.BundleProcessorTest.bundlePluginShouldNotBeNull(BundleProcessorTest.java:22)
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))
Also, this error might show up because you use argument matchers with
methods that cannot be mocked. Following methods cannot be
stubbed/verified: final/private/equals()/hashCode().
at
bundle.test.BundleProcessorTest.bundlePluginCollectionShouldNotBeNull(BundleProcessorTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
Please find below simplified code listing :-
BundlePlugin.java
package bundle;
import java.util.List;
public class BundlePlugin {
private final String pluginName ;
private final List<String> featureContent ;
public BundlePlugin(String pluginName, List<String> featureContent) {
super();
this.pluginName = pluginName;
this.featureContent = featureContent;
}
public String getPluginName() {
return pluginName;
}
public List<String> getFeatureContent() {
return featureContent;
}
}
BundleProcessor.java
package bundle;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class BundleProcessor {
public BundlePlugin getBundlePlugin(String pluginName, Iterator<String> artifactIterator) {
List<String> featureContent = new ArrayList<String>() ;
return new BundlePlugin(pluginName, featureContent);
}
}
BundleProcessorTest.java
package bundle.test;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
import bundle.BundleProcessor;
public class BundleProcessorTest {
BundleProcessor bundleProcessor = new BundleProcessor() ;
#Test
public void bundlePluginShouldNotBeNull() {
Iterator<String> artifactIterator = mock(Iterator.class) ;
bundle.BundlePlugin bundlePlugin = bundleProcessor.getBundlePlugin(anyString(), artifactIterator) ;
assertNotNull( bundlePlugin );
}
#Test
public void bundlePluginContentShouldNotBeNull() {
Iterator<String> artifactIterator = mock(Iterator.class) ;
bundle.BundlePlugin bundlePlugin = bundleProcessor.getBundlePlugin(anyString(), artifactIterator) ;
List<String> featureContent = bundlePlugin.getFeatureContent() ;
assertNotNull( featureContent );
}
}
How to execute this test without problem.
Edit 1:
But if i mark the bundlePluginCollectionShouldNotBeNull test with #Ignore annotation, then first test case passes without any exception.
You are using mockito anyString() while calling the test method, it should be used only for verifying a mock object to ensure a certain method is called with any string parameter inside the test, but not to invoke the test itself. For your test use empty string "" instead to anyString().
Ideally anyString() should not be used outside the mock or verify block. I was facing the same issue.Changing the anyString() to some string ("xyz") value works fine.
Note : Make a note that you might use anyString() to some other methods that leads in failure of some other method. It wasted my one hour to figure it out. My actual test method was getting passes individually but when i was trying to run that in a hole it was getting failed because of the reason that some other test case was using anyString() outside to mock or verify block.
We need to add a text file to the project's src/test/resources/mockito-extensions directory named org.mockito.plugins.MockMaker and add a single line of text:
mock-maker-inline
please refer article https://www.baeldung.com/mockito-final
Simple, Should use #Spy annotation with #InjectMocks annotation.

Functional test in java, explanation

This is a sample program:
public class FunctionalTest {
public int f(int r) {
int result = r * 5;
return result;
}
public static void main(String[] args) {
FunctionalTest funct = new FunctionalTest();
System.out.println(funct.f(5));
}
}
I'm a beginner.
How to write a functional test for this code?
How to write functional tests? Do I need to TestNG?
Is it enough to write the examination method?
Could someone explain to me and write a sample functional test for this program?
Well, if you're specifically asking for functional testing, there's not much you can do with that code snippet. You can do a unit test from the f method using JUnit like this:
#Test
public void testF(){
FunctionalTest t1 = new FunctionalTest();
assertEquals((t1.f(1) % 5), 0); //checks that is getting multiplied by 5.
}
However, you want functional testing, so by running your compiled app and assessing the result you're testing your app functionality by multiple units (AKA integration): your f method and your main method.
Regards!
First of all, you need to have a clear definition of contract you want to verify. From the code, I assume it is something like "the method should return the number equal to argument multiplied by 5".
TestNG, JUnit or other test frameworks is not mandatory for your case. The test may look like:
public void testF() {
int arg = 5;
int result = new FunctionalTest().f(arg);
assert result == arg * 5;
}
Also please keep in mind that to use assert you need JVM started with -ea flag.
Beware the terms you used:
the functional testing provide values to your user/customer
That implies:
black box testing: you have to test your whole system (hard+soft)
the test should target your user/customer needs (explicit report or test)
You can use whatever you want to test the feature (from unit test to jbehave).
In your case (using JUnit 4 and AssertJ):
import org.assertj.core.api.Assertions;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
/*
As an user
I want have 25 whatever I sent
*/
public class NumberGenerationTest {
private static final String PATH = "directory of your class file";
private InputStream stdout;
/* Nominal case */
#Test
public void shall_return_number_25_when_called_with_5() throws Exception {
when_I_call_FunctionalTest_with("5");
then_it_returns("25");
}
/* Nominal case or potential error case */
#Test
public void shall_return_number_25_when_called_with_10() throws Exception {
when_I_call_FunctionalTest_with("10");
then_it_returns("25");
}
/* Nominal case or potential error case */
#Test
public void shall_return_number_25_when_called_with_ABC() throws Exception {
when_I_call_FunctionalTest_with("ABC");
then_it_returns("25");
}
private void when_I_call_FunctionalTest_with(String parameter) throws Exception {
ProcessBuilder builder = new ProcessBuilder("java" ,"-classpath", PATH,"FunctionalTest" , parameter);
builder.redirectErrorStream(true);
Process process = builder.start();
stdout = process.getInputStream ();
}
private void then_it_returns(String expectedResult) throws Exception {
BufferedReader reader = new BufferedReader (new InputStreamReader(stdout));
String line = reader.readLine ();
Assertions.assertThat(line).isNotNull();
Assertions.assertThat(line).isEqualTo(expectedResult);
}
}
It seems you have an error in your main() ... or not.

Easy way of running the same junit test over and over?

Like the title says, I'm looking for some simple way to run JUnit 4.x tests several times in a row automatically using Eclipse.
An example would be running the same test 10 times in a row and reporting back the result.
We already have a complex way of doing this but I'm looking for a simple way of doing it so that I can be sorta sure that the flaky test I've been trying to fix stays fixed.
An ideal solution would be an Eclipse plugin/setting/feature that I am unaware of.
The easiest (as in least amount of new code required) way to do this is to run the test as a parametrized test (annotate with an #RunWith(Parameterized.class) and add a method to provide 10 empty parameters). That way the framework will run the test 10 times.
This test would need to be the only test in the class, or better put all test methods should need to be run 10 times in the class.
Here is an example:
#RunWith(Parameterized.class)
public class RunTenTimes {
#Parameterized.Parameters
public static Object[][] data() {
return new Object[10][0];
}
public RunTenTimes() {
}
#Test
public void runsTenTimes() {
System.out.println("run");
}
}
With the above, it is possible to even do it with a parameter-less constructor, but I'm not sure if the framework authors intended that, or if that will break in the future.
If you are implementing your own runner, then you could have the runner run the test 10 times. If you are using a third party runner, then with 4.7, you can use the new #Rule annotation and implement the MethodRule interface so that it takes the statement and executes it 10 times in a for loop. The current disadvantage of this approach is that #Before and #After get run only once. This will likely change in the next version of JUnit (the #Before will run after the #Rule), but regardless you will be acting on the same instance of the object (something that isn't true of the Parameterized runner). This assumes that whatever runner you are running the class with correctly recognizes the #Rule annotations. That is only the case if it is delegating to the JUnit runners.
If you are running with a custom runner that does not recognize the #Rule annotation, then you are really stuck with having to write your own runner that delegates appropriately to that Runner and runs it 10 times.
Note that there are other ways to potentially solve this (such as the Theories runner) but they all require a runner. Unfortunately JUnit does not currently support layers of runners. That is a runner that chains other runners.
With IntelliJ, you can do this from the test configuration. Once you open this window, you can choose to run the test any number of times you want,.
when you run the test, intellij will execute all tests you have selected for the number of times you specified.
Example running 624 tests 10 times:
With JUnit 5 I was able to solve this using the #RepeatedTest annotation:
#RepeatedTest(10)
public void testMyCode() {
//your test code goes here
}
Note that #Test annotation shouldn't be used along with #RepeatedTest.
I've found that Spring's repeat annotation is useful for that kind of thing:
#Repeat(value = 10)
Latest (Spring Framework 4.3.11.RELEASE API) doc:
org.springframework.test.annotation
Unit Testing in Spring
Inspired by the following resources:
blog post
this solution
commented version
Example
Create and use a #Repeat annotation as follows:
public class MyTestClass {
#Rule
public RepeatRule repeatRule = new RepeatRule();
#Test
#Repeat(10)
public void testMyCode() {
//your test code goes here
}
}
Repeat.java
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention( RetentionPolicy.RUNTIME )
#Target({ METHOD, ANNOTATION_TYPE })
public #interface Repeat {
int value() default 1;
}
RepeatRule.java
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class RepeatRule implements TestRule {
private static class RepeatStatement extends Statement {
private final Statement statement;
private final int repeat;
public RepeatStatement(Statement statement, int repeat) {
this.statement = statement;
this.repeat = repeat;
}
#Override
public void evaluate() throws Throwable {
for (int i = 0; i < repeat; i++) {
statement.evaluate();
}
}
}
#Override
public Statement apply(Statement statement, Description description) {
Statement result = statement;
Repeat repeat = description.getAnnotation(Repeat.class);
if (repeat != null) {
int times = repeat.value();
result = new RepeatStatement(statement, times);
}
return result;
}
}
PowerMock
Using this solution with #RunWith(PowerMockRunner.class), requires updating to Powermock 1.6.5 (which includes a patch).
Anything wrong with:
#Test
void itWorks() {
// stuff
}
#Test
void itWorksRepeatably() {
for (int i = 0; i < 10; i++) {
itWorks();
}
}
Unlike the case where you are testing each of an array of values, you don't particularly care which run failed.
No need to do in configuration or annotation what you can do in code.
This works much easier for me.
public class RepeatTests extends TestCase {
public static Test suite() {
TestSuite suite = new TestSuite(RepeatTests.class.getName());
for (int i = 0; i < 10; i++) {
suite.addTestSuite(YourTest.class);
}
return suite;
}
}
There's an Intermittent annotation in the tempus-fugit library which works with JUnit 4.7's #Rule to repeat a test several times or with #RunWith.
For example,
#RunWith(IntermittentTestRunner.class)
public class IntermittentTestRunnerTest {
private static int testCounter = 0;
#Test
#Intermittent(repition = 99)
public void annotatedTest() {
testCounter++;
}
}
After the test is run (with the IntermittentTestRunner in the #RunWith), testCounter would be equal to 99.
This is essentially the answer that Yishai provided above, re-written in Kotlin :
#RunWith(Parameterized::class)
class MyTest {
companion object {
private const val numberOfTests = 200
#JvmStatic
#Parameterized.Parameters
fun data(): Array<Array<Any?>> = Array(numberOfTests) { arrayOfNulls<Any?>(0) }
}
#Test
fun testSomething() { }
}
I build a module that allows do this kind of tests. But it is focused not only in repeat. But in guarantee that some piece of code is Thread safe.
https://github.com/anderson-marques/concurrent-testing
Maven dependency:
<dependency>
<groupId>org.lite</groupId>
<artifactId>concurrent-testing</artifactId>
<version>1.0.0</version>
</dependency>
Example of use:
package org.lite.concurrent.testing;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import ConcurrentTest;
import ConcurrentTestsRule;
/**
* Concurrent tests examples
*/
public class ExampleTest {
/**
* Create a new TestRule that will be applied to all tests
*/
#Rule
public ConcurrentTestsRule ct = ConcurrentTestsRule.silentTests();
/**
* Tests using 10 threads and make 20 requests. This means until 10 simultaneous requests.
*/
#Test
#ConcurrentTest(requests = 20, threads = 10)
public void testConcurrentExecutionSuccess(){
Assert.assertTrue(true);
}
/**
* Tests using 10 threads and make 20 requests. This means until 10 simultaneous requests.
*/
#Test
#ConcurrentTest(requests = 200, threads = 10, timeoutMillis = 100)
public void testConcurrentExecutionSuccessWaitOnly100Millissecond(){
}
#Test(expected = RuntimeException.class)
#ConcurrentTest(requests = 3)
public void testConcurrentExecutionFail(){
throw new RuntimeException("Fail");
}
}
This is a open source project. Feel free to improve.
You could run your JUnit test from a main method and repeat it so many times you need:
package tests;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.Result;
public class RepeatedTest {
#Test
public void test() {
fail("Not yet implemented");
}
public static void main(String args[]) {
boolean runForever = true;
while (runForever) {
Result result = org.junit.runner.JUnitCore.runClasses(RepeatedTest.class);
if (result.getFailureCount() > 0) {
runForever = false;
//Do something with the result object
}
}
}
}

Categories