How can I JUnit test "printlist"? - java

I have been staring at this code for quite some time now and I really can't figure out how and what to do for its JUnit testing.
static void printList(OrderedIntList list) {
System.out.print("[");
for (int i = 0; i < list.orderedIntegerList.length; i++) {
System.out.print(list.orderedIntegerList[i]);
if (i != list.orderedIntegerList.length - 1) {
System.out.print(", ");
}
}
System.out.println("]");
}
This code is from a utility class called orderedIntList, which is an array list.

Well... think about the contracts of this method: What does it promise? It promises to print a list of integers, separated by a comma, and inside of brackets. So, you could specify this in a unit test.
Edit2: Just in case you fancy unit testing whether the list is printed in order: I would not consider this a property of the printList method. This property should be tested in the methods that modify the OrderedIntList.
Write a fixture for some Lists with the string that you expect to be printed. Don't forget the corner case: An empty list. Then, maybe a list of size 1 and one of size 10.
To check what has been printed, you can create a new PrintStream, and set the value of System.out, by calling System.setOut. Do this at the beginning of each test, and don't forget to reset System.out (so don't forget to store its original value). The PrintStream you use need not be fancy: You simply must be able to compare the printed stream. You may want to consider using Mockito for that matter.
Edit:
For example, the following code tests whether the list containing the sole element 4, actually prints the string "[4]\n":
#Test
public void aListOfSizeOneShouldPrintTheElementWithinBrackets() {
/* Setup */
final StringBuffer printStream = new StringBuffer();
PrintStream mockedOut = mock(PrintStream.class);
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString());
return null;
}
}).when(mockedOut).print(any());
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString());
return null;
}
}).when(mockedOut).print(anyString());
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString()).append("\n");
return null;
}
}).when(mockedOut).println(any());
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString()).append("\n");
return null;
}
}).when(mockedOut).println(anyString());
PrintStream originalOut = System.out;
System.setOut(mockedOut);
/* the actual test */
ArrayList<Integer> listWithOneElement = new ArrayList<Integer>();
listWithOneElement.add(4);
OrderedIntList list = new OrderedIntList(listWithOneElement);
OrderedIntList.printList(list);
MatcherAssert.assertThat(printStream.toString(), is("[4]\n"));
/* Teardown - reset System.out */
System.setOut(originalOut);
}
Note that you probably want to extract the setup- and the teardown part to use it in other tests and to make your test readable. If I am not mistaken, JUnit provides functionality to add code that gets invoked before and after each test execution if you specify it with an #Before and #After annotation.
Obviously, you do not necessarily need Mockito to achieve this. You can also write a class that implements PrintStream and stores the printed strings. In this case, Mockito simply allows you to ignore all the methods you do not care about (i.e., you do not need to implement the whole PrintStream interface)
A small sidenote on the duplication of the stubing: We need to stub both methods, print and println, because both are used. Also, because of overriding, print(String x) is not the same as print(Object x), so we need to stub them both.

#Kulu Limpa answer is correct but much more complicated than the actual implementation, because you need some mocking.
if you refactor your code to
static void printList(OrderedIntList list) {
System.out.println(toString(list));
}
static String toString(OrderedIntList list) {
StringBuilder result = new StringBuilder();
System.out.println(toString(list));
result.append("[");
for (int i = 0; i < list.orderedIntegerList.length; i++) {
result.append(list.orderedIntegerList[i]);
if (i != list.orderedIntegerList.length - 1) {
result.append(", ");
}
}
result.append("]");
return result.toString();
}
testing should be much easier:
#Test
public void aListOfSizeOneShouldPrintTheElementWithinBrackets() {
ArrayList<Integer> listWithOneElement = new ArrayList<Integer>();
listWithOneElement.add(4);
OrderedIntList list = new OrderedIntList(listWithOneElement);
String result = OrderedIntList.toString(list);
MatcherAssert.assertThat(result, is("[4]"));
}

The library System Rules has a JUnit rule called StandardOutputStreamLog. With this rule you are able to test your code, that writes to System.out:
public void MyTest {
#Rule
public final StandardOutputStreamLog log = new StandardOutputStreamLog();
#Test
public void test() {
OrderedIntList list = ...
printList(list);
assertEquals("[1,2,3,4]", log.getLog());
}
}

Related

Choose which methods to run, with user input

I have a list of methods within my class. And then want to have input string array, where the user can choose which methods they want to run. We are running expensive insurance calculations. And have over say eg 20 methods. Is there a way to conduct this without do an if check on each? maybe with reflection or interface?
#Override
public void ProductTest(ProductData productData, String[] methodNames) {
public void methodA(ProductData productData){...};
public void methodB(ProductData productData){...};
public void methodC(ProductData productData){...};
public void methodD(ProductData productData){...};
public void methodE(ProductData productData){...};
}
I am willing to change the Array into a different ObjectType if needed, to execute properly. Using SpringBoot, has it has a library of utility classes.
Use a Map<String, Consumer<ProductData>>, not separate method handles. Main reason - reflection is slow and dangerous when given user "input"
Use map.get(input).accept(product) to call it.
https://docs.oracle.com/javase/8/docs/api/index.html?java/util/function/Consumer.html
Example
Map<String, Consumer<ProductData>> map = new HashMap<>();
map.put("print_it", System.out::println);
map.put("print_id", data -> System.out.println(data.id));
map.put("id_to_hex", data -> {
int id = data.getId();
System.out.printf("0x%x%n", id);
});
ProductData data = new ProductData(16);
map.get("print_it").accept(data);
map.get("print_id").accept(data);
map.get("id_to_hex").accept(data);
Outputs
ProductData(id=16)
16
0x10
If you are planning on chaining consumers using andThen, you'd be better having an Optional<ProductData>, and using a Function<ProductData, ProductData> with Optional.map()
One way to do it is via reflection. You can iterate over methods in the class object and look for ones to run by name. Here's some example code--this would print out a list of names the user could type in:
myObject.getClass().getDeclaredMethods().each((method)->System.out.println(method.getName()))
And this is how you would call it once the user had made a selection:
productTest.getDeclaredMethods().each((method)->
if(method.getName().equals(userSelectedName))
method.invoke(productTest, productData)
)
The ONLY advantage to this approach is that you don't have to maintain a second structure (Switch, Map, etc...) and add to it every time you add a new method. A personality quirk makes me unwilling to do that (If adding something one place forces you to update a second, you're doing it wrong), but this doesn't bother everyone as much as it bothers me.
This isn't dangerous or anything, if you don't have a method in the class it can't call it, but if you are relying on users "Typing", I'd suggest listing out the options and allowing a numeric selection--or using reflection to build a map like OneCricketeer's.
I've used this pattern to write a testing language and fixture to test set-top TV boxes, it was super simple to parse a group of strings, map some to methods and other to parameters and have a very flexible, easily extensible testing language.
The method object also has a "getAnnotation()" which can be used to allow more flexible matching in the future.
You can use method invocation.
For example, you can have two methods, first one will loop through your methodNames array and call the second method:
public void callPassedMethods(ProductData productData, String[] methodNames) {
for (String m : methodNames) {
callMethod(productData, m)
}
}
And the second method will actually find a method in your class that matches the string passed and invoke it:
public void callMethod(ProductData productData, String methodName) {
try {
ClassName yourObj = new ClassName(); // Class where your methods are
Method method = yourObj.getClass().getDeclaredMethod(methodName, ProductData.class);
method.invoke(yourObj, productData);
} catch(NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// handle exceptions
}
}
Or, you can always use the good old switch statement:
for (String m : methodNames) {
switch (m) {
case "methodA":
methodA();
break;
case "methodB":
methodB();
break;
// ... continue with as many cases as you need
}
}
If you go with the reflection route, you don't really want to expose your method names to the end users. They might not be end user-friendly, and if they are, there is no reason for users to know this information and there might be methods, which are not supposed to be invoked by users. I would use custom annotations to build more flexible matching.
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface UserChoice {
String userFriendlyOption();
int optionNumber();
}
optionNumber will be used for matching the method to invoke, userFriendlyOption is some user friendly text.
Annotate only the methods, supposed to be used by users.
#RequiredArgsConstructor
public class ProductData {
private final double data;
#UserChoice(userFriendlyOption = "see result for option a", optionNumber = 1)
public void methodA() {
System.out.println(data + 1);
}
#UserChoice(userFriendlyOption = "see result for option b", optionNumber = 2)
public void methodB() {
System.out.println(data + 2);
}
#UserChoice(userFriendlyOption = "see result for option c", optionNumber = 3)
public void methodC() {
System.out.println(data);
}
public void methodNotForUser() {
System.out.println("Should not be seen by users");
}
}
Like this methodNotForUser() can't be invoked by end users.
Simplified matcher might look like this.
#RequiredArgsConstructor
public class ProductTester {
private final ProductData data;
private Map<Integer, MethodData> map;
public void showOptions() {
if (this.map == null) {
this.map = new HashMap<>();
for (Method method : this.data.getClass().getMethods()) {
UserChoice userChoice = method.getAnnotation(UserChoice.class);
if (userChoice != null) {
String userRepresentation = userChoice.optionNumber() + " - " + userChoice.userFriendlyOption();
this.map.put(userChoice.optionNumber(), new MethodData(userRepresentation, method));
}
}
}
this.map.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry -> System.out.println(entry.getValue().getUserRepresentation()));
}
public void showOptionResult(int choice) {
MethodData methodData = this.map.get(choice);
if (methodData == null) {
System.out.println("Invalid choice");
return;
}
System.out.println("Result");
try {
methodData.getMethod().invoke(this.data);
} catch (IllegalAccessException | InvocationTargetException ignore) {
//should not happen
}
}
}
MethodData is simple pojo with the sole purpose to not recalculate user representation.
#RequiredArgsConstructor
#Getter
public class MethodData {
private final String userRepresentation;
private final Method method;
}
Short main to illustrate the idea and play around:
public class Temp {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Write initial value");
double data = scanner.nextDouble();
ProductData myData = new ProductData(data);
ProductTester tester = new ProductTester(myData);
tester.showOptions();
System.out.println("Write option number");
int userChoice = scanner.nextInt();
tester.showOptionResult(userChoice);
}
}

How to run methods in benchmarks sequentially with JMH?

In my scenario, the methods in benchmark should run sequentially in one thread and modify the state in order.
For example, there is a List<Integer> called num in the benchmark class. What I want is: first, run add() to append a number into the list. Then, run remove() to remove the number from the list.
The calling sequence must be add() --> remove(). If remove() runs before add() or they run concurrently, they would raise exceptions because there's no element in the list.
That is, add() and remove() must be called sequentially and in one thread.
In Control the order of methods using JMH, I learned that the methods run in the lexicographical order. I tried the code below:
#State(Scope.Group)
#OutputTimeUnit(TimeUnit.MILLISECONDS)
#BenchmarkMode(Mode.AverageTime)
#Fork(value = 10)
public class ListBenchmark {
private List<Integer> num;
public static void main(String[] args) throws RunnerException {
Options options = new OptionsBuilder()
.verbosity(VerboseMode.NORMAL)
.syncIterations(true)
.threads(1)
.include(".*" + ListBenchmark.class.getCanonicalName() + ".*")
.build();
new Runner(options).run();
}
#Setup(Level.Invocation)
public void setup() throws Exception {
num = new ArrayList<>();
}
#Benchmark
#BenchmarkMode(Mode.SingleShotTime)
#Group("num")
public void add() throws Exception {
num.add(1);
}
#Benchmark
#BenchmarkMode(Mode.SingleShotTime)
#Group("num")
public void remove() throws Exception {
num.remove(0);
}
}
But it doesn't work, because the add method and the remove method run concurrently. In some cases, the remove runs before add and raises IndexOutOfBoundsException.
How to run the methods in benchmarks sequentially with JMH?
You start with a wrong precondition and everything fails short because of that. You can see a broader explanation from the authors here. You want symmetry where asymmetry is implied.
If you want to see how much it takes add -> remove place them both in the same #Benchmark, and same for individual add or remove via different State. For example:
#State(Scope.Thread)
public static class BothAddAndRemove {
List<Integer> num;
#Setup(Level.Invocation)
public void setup() throws Exception {
num = new ArrayList<>();
}
}
#State(Scope.Thread)
public static class RemoveOnly {
List<Integer> num;
#Setup(Level.Invocation)
public void setup() throws Exception {
num = new ArrayList<>();
num.add(1);
}
}
#Fork(25)
#Benchmark
#BenchmarkMode(Mode.SingleShotTime)
public int add(BothAddAndRemove both) {
both.num.add(1);
return both.num.remove(0);
}
#Fork(25)
#Benchmark
#BenchmarkMode(Mode.SingleShotTime)
public int removeOnly(RemoveOnly removeOnly) {
return removeOnly.num.remove(0);
}

Mockito Assert resulting NullPointerException

I am writing a simple test case but getting a null pointer exception in the return value.
Although when I debug the actual mocking is working , and my main code is also being triggered
My Test Case
#Test
public void testEmptyRequests() {
List<MyPojo> list = new ArrayList();
String env = "env-stub";
when(myService.fetchRecords(env)).thenReturn(list);
Assert.assertEquals(Integer.valueOf(0), myController.process(env, 1));
}
My Method
#Async
public Integer process(String environment, Integer id) {
List<MyPojo> list = myService.fetchRecords(environment);
if (list == null || list .isEmpty()) {
log.info("[0] claims to process");
return 0;
}
// Other logic here, Not relevant to this test case
}
change your test method to this:
#Test
public void testEmptyRequests() {
List<MyPojo> list = new ArrayList();
String env = "env-stub";
when(myService.fetchRecords(Mockito.anyString())).thenReturn(list);
Assert.assertEquals(Integer.valueOf(0), myController.process(env, 1));
}
You should mock the method you are using inside your code.

How to make Unit test passed with use Mockito?

How I understand Mockito.mock create the stub of the service (or another object).
I have simple handler:
public class Handler
{
private HttpSender sender;
public Handler(BigInteger sessiongId) {
RequestHelper helper = RequestHelper.getInstance();
String requestAsText = helper.getCurrentRequest(sessiongId);
StringBuilder stringBuilder = new StringBuilder(requestAsText);
run(stringBuilder);
sender = SenderGenerator.getInstance().create(stringBuilder.toString());
}
public void run(StringBuilder str) {
str.delete(0, 2);
}
}
How I can pass test for this handler with use Mockito?
public class HandlerTest
{
#Test
public void testRun()
{
StringBuilder str = new StringBuilder("1234");
Handler handler = Mockito.mock(Handler.class);
handler.run(str);
Assert.assertEquals("34", str);
}
}
The actual result of this test is 1234 ? Why ?
Because your haldler object in the test method is a mock-object and not a real object the method call handler.run(str) will not do anything as long as you don't tell it what to do.
So a solution would be to tell the mock object to call the real method like this:
public class HandlerTest {
#Test
public void testRun() {
StringBuilder str = new StringBuilder("1234");
Handler handler = Mockito.mock(Handler.class);
when(handler.run(any(StringBuilder.class))).thenCallRealMethod();
handler.run(str);
Assert.assertEquals("34", str.toString());//add toString here, because you are comparing a String to a StringBuilder
}
}
Another way of testing this method would be to make it static so you dont even need to mock anything:
public class Handler {
public Handler(BigInteger sessiongId) {
//...
}
public static void run(StringBuilder str) {
str.delete(0, 2);
}
}
And your test method would look like this:
public class HandlerTest {
#Test
public void testRun() {
StringBuilder str = new StringBuilder("1234");
Handler.run(str);
Assert.assertEquals("34", str.toString());
}
}
Two things:
1. You have mocked the very class you want to test. And you haven't defined any specific behaviour for the mock either. So the call to the test method itself is skipped. You may have to think over what was the purpose of mocking?
2. You are comparing a StringBuilder object with a String, that needs to be corrected too.

Check if a method was called inside another method

Is there any way in java to check if a certain method was called inside another method? I am testing a class and the method I am having trouble with plays sound and there is virtually no way of getting the audio file that is played(private attribute inside an inner class) without changing the code. However the way the method plays sounds is it calls a method that plays a single sound (playSadMusic, playHappyMusic, etc). Those methods are in an interface that I have to create a mock object for. I'm a little stuck on how I would exactly go about testing this. Any thoughts? Any other ideas on how I could possibly test this other than check if a certain method was call are welcome.
I am using JMock 2.6.0 and JUnit 4
the audio inteface
public interface StockTickerAudioInterface {
public abstract void playHappyMusic();
public abstract void playSadMusic();
public abstract void playErrorMusic();
}
anther interface I have to create a mock for
public interface StockQuoteGeneratorInterface {
public abstract StockQuoteInterface getCurrentQuote() throws Exception;
public abstract String getSymbol();
public abstract void setSymbol(String symbol);
public abstract StockQuoteGeneratorInterface createNewInstance(String symbol);
}
the class being tested
public class StockQuoteAnalyzer {
private StockTickerAudioInterface audioPlayer = null;
private String symbol;
private StockQuoteGeneratorInterface stockQuoteSource = null;
private StockQuoteInterface lastQuote = null;
private StockQuoteInterface currentQuote = null;
public StockQuoteAnalyzer(String symbol,
StockQuoteGeneratorInterface stockQuoteSource,
StockTickerAudioInterface audioPlayer)
throws InvalidStockSymbolException, NullPointerException,
StockTickerConnectionError {
super();
// Check the validity of the symbol.
if (StockTickerListing.getSingleton().isValidTickerSymbol(symbol) == true){
this.symbol = symbol;
} else {
throw new InvalidStockSymbolException("Symbol " + symbol
+ "not found.");
}
if (stockQuoteSource == null) {
throw new NullPointerException(
"The source for stock quotes can not be null");
}
this.stockQuoteSource = stockQuoteSource;
this.audioPlayer = audioPlayer;
}
public double getChangeSinceLast() {
double retVal = 0.0;
if (this.lastQuote != null) {
double delta = this.currentQuote.getLastTrade() - this.lastQuote.getLastTrade();
retVal = 100 * (delta / this.lastQuote.getLastTrade());
}
return retVal;
}
public double getChangeSinceYesterday() {
double delta = (this.currentQuote.getLastTrade() - this.currentQuote
.getClose());
return 100 * (delta / this.currentQuote.getClose());
}
public void playAppropriateAudio() {
if ((this.getChangeSinceYesterday() > 2)
|| (this.getChangeSinceLast() > 0.5)) {
audioPlayer.playHappyMusic();
}
if ((this.getChangeSinceYesterday() < -2)
|| (this.getChangeSinceLast() < -0.5)) {
audioPlayer.playSadMusic();
}
}
}
If you use Mockito you can use verify() to check the number of times a method was called. Use it like this:
verify(mockedObject, times(1)).methodToValidate();
You can check if methodToValidate() was called with a specific string, e.i verify(mockedObject, times(1)).methodToValidate("a specific value"); or you can use it with anyString() like this: verify(mockedObject, times(1)).methodToValidate(anyString());.
Unless this method is called with your specified paramterer, the test will fail
Read more about verify here.
UPDATE
Since your edited post states that you are using jMock, a quick googeling showed me that it is possible to achieve a similar behaviour with jMock and it's expect method. It's used as below:
mockedObject.expects(once()).method("nameOfMethod").with( eq("An optional paramter") );
More detailed explanation can be found by reading jMocks getting started page.
say you have a method child() which is called in parent()
public void parent() {
child();
}
In child() to get the last method it got invoked from, you can use StackTraceElement
public void child() {
StackTraceElement[] traces = Thread.currentThread().getStackTrace();
boolean check = false;
for(StackTraceElement element : traces) {
if(check) {
System.out.println("Calling method - " + element.getMethodName());
}
if(element.getMethodName().equals("child")) {
check = true;
}
}
}
If you are writing a mock object with the methods you want to check whether they were called, you can implement the methods in a way they raise some flag when they are called, for example
public void playHappyMusic() {
this.wasCalled = true;
}
wasCalled being a public (or with getters) class variable. Then you just check the flag.
Provide you are in the same thread as the calling method, you can check the stack trace in any given moment this way:
Thread.currentThread().getStackTrace()
You can see what method are called doing it like this:
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
For example:
public class Test {
public static void main (String[]s){
Test test = new Test();
test.makeTest();
}
public void makeTest(){
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
}
results in
java.lang.Thread.getStackTrace(Unknown Source)
Test.makeTest(Test.java:17)
Test.main(Test.java:11)

Categories

Resources