Assume I want to test code like this:
class ClassToTest
// UsedClass1 contains a method UsedClass2 thisMethod() {}
UsedClass1 foo;
void aMethod()
{
int max = new Random().nextInt(100);
for(i = 0; i < max; i++)
{
foo.thisMethod().thatMethod();
}
}
}
If I have a test like this:
ClassToTest test;
UsedClass1 uc1;
UsedClass2 uc2;
#Test
public void thingToTest() {
test = new ClassToTest();
uc1 = mock(UsedClass1.class);
uc2 = mock(UsedClass2.class);
when(uc1.thisMethod()).thenReturn(uc2);
when(uc2.thatMethod()).thenReturn(true);
test.aMethod();
// I would like to do this
verifyEquals(callsTo(uc1.thisMethod()), callsTo(uc2.thatMethod()));
}
How can I get the number of calls to uc1.thisMethod() and uc2.thatMethod() so I can check they were both called the same number of times?
You can do something like this:
YourService serviceMock = Mockito.mock(YourService.class);
// code using YourService
// details of all invocations including methods and arguments
Collection<Invocation> invocations = Mockito.mockingDetails(serviceMock).getInvocations();
// just a number of calls of any mock's methods
int numberOfCalls = invocations.size();
If you want only the invocations of certain method/param combination you, you can do so with
int specificMethodCall = Mockito.mockingDetails(serviceMock.myMethod(myParam)).getInvocations()
You could stub your methods, and increment a counter, like this:
final AtomicInteger countCall1 = new AtomicInteger();
Mockito.doAnswer(new Answer<UsedClass2>() {
#Override
public UsedClass2 answer(InvocationOnMock invocation) throws Throwable {
countCall1.incrementAndGet();
return uc2;
}
}).when(uc1).thisMethod();
If you know the number of times a method is suppoed to be called you can use the times() method of Mockito
//for example if had to be called 3 times
verify(uc1, times(3)).thisMethod();
verify(uc2, times(3)).thatMethod();
However, I now see that you call the method a random number of times, so this probably isn't the best answer unless you stub out the random number generator to always return an expected value.
You can use a custom VerificationMode to count the invocations, here you go:
public class InvocationCounter {
public static <T> T countInvocations(T mock, AtomicInteger count) {
return Mockito.verify(mock, new Counter(count));
}
private InvocationCounter(){}
private static class Counter implements VerificationInOrderMode, VerificationMode {
private final AtomicInteger count;
private Counter(AtomicInteger count) {
this.count = count;
}
public void verify(VerificationData data) {
count.set(data.getAllInvocations().size());
}
public void verifyInOrder(VerificationDataInOrder data) {
count.set(data.getAllInvocations().size());
}
#Override
public VerificationMode description(String description) {
return VerificationModeFactory.description(this, description);
}
}
}
And then use it like this (works also with void return types):
#Mock
private Function<String, Integer> callable;
AtomicInteger count= new AtomicInteger(); //here is the actual invocation count stored
countInvocations(callable,count).apply( anyString());
assertThat(count.get(),is(2));
Related
I want to make a simple program to compare how long time takes rewrite and print out collection of Strings by `for loop`, `foreach` or `stream`. String is sentence where it replaces "i" by "y". In my case I made `count()` where I set to count `stream()` method but I want to make universal measuring method. But i dont know how to do it... It should works like: in Main class is `counter(forLoop);` It should call `forLoop();` from Method class `counter(forEach);` It should call `forEach();` from Metrod class`counter(stream);` It should call ` stream();` From Method class IDont know how to pass method as a parameter
I have class where are those metods:
import java.util.*;
import java.util.stream.*;
public class Methods {
private List<String> sentence = new ArrayList<>();
private String oldLetter = "i";
private String newLetter = "y";
private String methodType;
public String getMethodType() {
return methodType;
}
//making a collection with String
public void setSizeOfCollection(int size){
for (int i = 0; i < size; i++) {
sentence.add("Siti Zbinek plitce zvikal sirovi pelinek.");
}
}
public void forLoop(){
methodType = "For loop";
for (int i = 0; i < sentence.size(); i++) {
for (int j = 0; j < sentence.size(); j++) {
String replaceLetters = sentence.get(j);
replaceLetters = replaceLetters.replaceAll(oldLetter, newLetter);
sentence.set(j, replaceLetters);
}
System.out.println(sentence.get(i));
}
}
public void forEach(){
methodType = "For each";
String replacedLetters = "";
for(String oneLine: sentence){
for(String originalLetters: sentence){
replacedLetters = originalLetters.replaceAll(oldLetter,newLetter);
}
System.out.println(replacedLetters);
}
}
public void stream(){
methodType= "Stream";
sentence.stream()
.map(e->e.replaceAll(oldLetter,newLetter))
.collect(Collectors.toList())
.forEach(System.out::println);
}
}
This is count() that works fine, but only for method stream(). In comment is my imagine how it should be. But I dont know how it do by Java :(
import org.apache.commons.lang.time.*;
public class Counter {
private Methods methods;
private String methodType;
private StopWatch stopWatch = new StopWatch();
long timeTaken = 0;
//here should be something like any method as a parameter XXX xxx
// public void count(Methods methods XXX xxx)
public void count(Methods methods){
stopWatch.start();
// here sould be something what call any function by your choice, not only stream()
// methods.xxx;
methods.stream();
stopWatch.stop();
timeTaken= stopWatch.getTime();
System.out.println(methods.getMethodType()+" takes "+ timeTaken + " ms." );
}
}
And finally Main class
public class Main {
public static void main(String[] args) {
Methods methods = new Methods();
Counter counter = new Counter();
methods.setSizeOfCollection(10000);
counter.count(methods);
//here should be finally three times method, with different parameters:
// counter.count(methods, forEach);
// counter.count(methods, forLoop);
// counter.count(methods, stream);
}
}
Any advice please?
All your methods have the signature void(). Consequently, a reference to each method can be stored in a Runnable instance.
public void count(final Runnable method) {
stopWatch.start();
method.run();
stopWatch.stop();
timeTaken= stopWatch.getTime();
System.out.println(methods.getMethodType()+" takes "+ timeTaken + " ms.");
}
And then call as:
final Methods methods = new Methods();
final Counter counter = new Counter();
methods.setSizeOfCollection(10000);
counter.count(methods::stream); // or count(() -> methods.stream());
counter.count(methods::forEach); // count(() -> methods.forEach());
counter.count(methods::loop); // count(() -> methods.loop());
To be able to use method refs or lambdas, you need to have at least Java 8. For earlier Java versions, you would need to implement Runnable with an anonymous class, e.g.
counter.count(new Runnable() {
#Override public void run() { methods.stream(); }
});
or look up the methods by name via Reflection, but Reflection is usually the slowest option.
PS. Note however that your way of measuring method execution times is flawed; see How do I write a correct micro-benchmark in Java? for directions. This answer only explains the part of passing "methods" to another method.
you could pass the method name as a string and look for it with reflexion.
I have created an array which I wanted to control from main. My code runs, but I don't know how to add integers to the array from the main class. Also as each ConcreteSubject has its own storage array, how would i change this to store them all in the same array?
public class ConcreteSubject extends AbstractSpy
{
private AbstractSpy[] spies = new AbstractSpy[10];
private int i = 0;
public void addSpy(AbstractSpy s) {
if (i < spies.length) {
spies[i] = s;
System.out.println("spy added at index " + i);
i++;
}
}
}
public class TestClass
{
public static void main(String[] args) {
ConcreteSubject cs = new ConcreteSubject();
AbstractSpy spies = new AbstractSpy() {
#Override
public void addSpy(AbstractSpy spies) {
}
};
cs.addSpy(cs);
spies.addSpy(spies);
}
}
It seems like your program logic is a little borked. This bit in particular doesn't make much sense:
***AbstractSpy spies = new AbstractSpy() {
#Override
public void addSpy(AbstractSpy spies) {
}
};
cs.addSpy(cs);
***spies.addSpy(spies);
What you're doing is creating TWO AbstractSpy instances, one named cs and one named spies. On that last line you're adding spies to itself! That doesn't help you at all.
Note that AbstractSpy is the most granular unit in your setup - it shouldn't have an addSpy() method and its own internal array, it should be the thing that's added to something else's array!
Here's the same code, but cleaned up a bit:
public abstract class AbstractSpy { }
public class ConcreteSpy extends AbstractSpy { }
public class ConcreteSubject {
private AbstractSpy[] spies = new AbstractSpy[10];
private int i = 0;
public void addSpy(AbstractSpy spy) {
if (i < spies.length)
{
spies[i] = spy;
System.out.println("spy added at index " + i);
i++;
}
}
}
public class TestClass {
public static void main(String[] args) {
ConcreteSubject cs = new ConcreteSubject();
AbstractSpy spy = new ConcreteSpy();
cs.addSpy(spy);
}
}
The big difference here is that ConcreteSpy is an implementation of AbstractSpy that you can add to your ConcreteSubject's array of spies. I think you might have been confused by Java's insistence that you can't create an instance of an abstract class on its own unless you supply an anonymous class that inherits from the abstract class.
I'm having problems with two void methods. In encouragedVenturesScoring I've followed this answer mocking an arraylist that will be looped in a for loop and haven't mocked the list, but passed a real list and added mocked objects.
Mockito gives me an InvalidUseOfMatchersException on this line
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
There are lots of questions on SO on this exception , and I think it's because of anyInt(). Anyway I changed it to
verify(effectList.get(0)).execute(playerHandler);
And now it's saying Wanted but not invoked effect.execute(playerHandler)
Actually there were zero interactions with this mock
Is it because I put doNothing ?
doNothing().when(effect).execute(playerHandler);
In my second method militaryStrengthScoring() method is there a way to skip the first chunk of code and just test the if..else condition? What would be the best approach to test this method?
Thank you for your time.
This is the class to be tested
public class EndGameScoringBaseController implements EndGameScoringHandler {
private static final int[] TERRITORIES_REWARD = {0,0,1,4,10,20};
private static final int[] CHARACTERS_REWARD = {1,3,6,10,15,21};
private static final int RESOURCES_RATE = 5;
private static final int FIRST_MILITARY_REWARD = 5;
private static final int SECOND_MILITARY_REWARD = 2;
private PlayerHandler player;
public EndGameScoringBaseController(PlayerHandler player) {
super();
this.player = player;
}
#Override
public void encouragedVenturesScoring() {
for (DevelopmentCard card : player.getPlayer().getPersonalBoard().getVentures()) {
for (Effect e : card.getPermanentEffects())
e.execute(player);
}
}
#Override
public void militaryStrengthScoring(GameController game) {
Set<Integer> points = new HashSet<>();
int myPoints = this.player.getPointsHandler().getMilitaryPoints();
for (PlayerHandler p: game.getPlayers()) {
points.add(p.getPointsHandler().getMilitaryPoints());
}
int[] rank = new int[points.size()];
int j = 0;
for (Integer i : points) {
rank[j] = i;
j++;
}
Arrays.sort(rank);
if (rank[rank.length-1] == myPoints) {
player.getPointsHandler().winMilitaryPoints(FIRST_MILITARY_REWARD);
}
else if (rank[rank.length-2] == myPoints) {
player.getPointsHandler().winVictoryPoints(SECOND_MILITARY_REWARD);
}
}
Tested method for encouragedVenturesScoring
#Test
public void encouragedVenturesScoringTest() {
//given
List<DevelopmentCard> ventureList;
ventureList = Arrays.asList(developmentCard, developmentCard);
when(playerHandler.getPlayer().getPersonalBoard().getVentures()).thenReturn(ventureList);
List<Effect> effectList;
effectList = Arrays.asList(effect, effect);
when(developmentCard.getPermanentEffects()).thenReturn(effectList);
doNothing().when(effect).execute(playerHandler);
//when
endgameController.encouragedVenturesScoring();
//then
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
}
Incomplete tested method for militaryStrengthScoring
#Test
public void militaryStrengthScoringTest() {
//given
when(playerHandler.getPointsHandler().getMilitaryPoints()).thenReturn(4);
doNothing().when(playerHandler.getPointsHandler()).winMilitaryPoints(FIRST_MILITARY_REWARD);
//when
endgameController.militaryStrengthScoring(gameController);
//then
/../
}
You're right that this is the problem:
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
Mockito only allows for calls like any() and anyInt() to stand in for parameters to the mock themselves, due to the internal implementation of matchers.
/* OK */ when(yourMock.yourMethod(anyInt())).thenReturn(42);
/* BAD */ when(yourList.get(anyInt()).yourMethod(0)).thenReturn(42);
/* OK */ verify(yourMock).yourMethod(anyInt());
/* BAD */ verify(yourList.get(anyInt())).yourMethod(0);
The failure with get(0) is likely an actual failure, and may be related to the fact that your encouragedVenturesScoringTest is actually not calling encouragedVenturesScoring, it's calling influencedCharactersScoring. If this continues to give you trouble after fixing that error, in ways related to Mockito, please edit your question.
You can only verify mock objects created by Mockito.
But effectList is a "real" list. Therefore Mockito knows nothing about that object. Thus any attempt to verify that list must fail.
If you want to verify that object - then you have to mock it!
Of course, this means that you have specify all calls that will go to the mocked list.
I have an existing Java class as follows and I want to monitor number of method invocations for each method in this class using JMX. How do I do it? I tried google but I can't see the big picture on how the whole thing is connected. It would be great if I can see see some code examples
Public class RPCServer {
public void storeSchema() { // want to count number of method invocations
System.out.println("storeSchema");
}
public void getSchema() { // want to count number of method invocations
System.out.println("getSchema");
}
public void storeRow() { // want to count number of method invocations
System.out.println("storeRow");
}
public void getRow() { //want to count number of method invocations
System.out.println("getRow");
}
}
I you want to see how many time some methods are executed through JMX, I propose this solution
First you need an interface for your class. Only the methods of this interface are visible for JMX:
public interface RPCServerInterface {
int countMethodInvocation(String method);
}
Then in the class you store how many time each function is call.
public class RPCServer implements RPCServerInterface{
private int row;
private Map<String,Integer> countByMethod = new HashMap<String,Integer>();
// +1 to the number of time of execution of this method
private void sumMethodInvocation(String method) {
if ( countByMethod.containsKey(method) ) {
int n = countByMethod.get(method);
countByMethod.put(method, n+1);
} else {
countByMethod.put(method,1);
}
}
// how many time the method has been invoked
#Override
public int countMethodInvocation(String method){
return countByMethod.containsKey(method)?countByMethod.get(method):0;
}
public void setRow(int i) {
// register each time is executed
this.sumMethodInvocation("setRow");
this.row = i;
}
public int getRow() {
// register each time is executed
this.sumMethodInvocation("getRow");
return row;
}
}}
}
Then you have to register your Bean:
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
RPCServer rpcServer = new RPCServer();
ObjectName objectName = new ObjectName("org.foo.RPCServer.jmx:type=RPCServerInterface");
StandardMBean standardMBean = new StandardMBean(rpcServer,RPCServerInterface.class);
mBeanServer.registerMBean(standardMBean, objectName);
The path org.foo.RPCServer.jmx is arbitrary.
Then your run jconsole and you find the process you are running.
Then you can run the command countMethodInvocation and you can get the number of execution time.
Like this:
This tutorial can be useful:
what-is-jmx-mbean-jconsole-tutorial
I'm trying to get some grasps over the Java 8 functional programming. I tried to write the following IntSupplier "functionally" but I keep getting issues.
import java.util.function.IntSupplier;
#Test public void test_nonFunctional() {
IntSupplier supplier = new IntSupplier() {
private int nextInt = 0;
#Override public int getAsInt() {
return nextInt++;
}
};
}
Here are my attempts. The issues are marked as comments in the code.
import org.junit.Test;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.IntSupplier;
public class IntSupplierTest {
#Test public void test_nonFunctional() {
IntSupplier supplier = new IntSupplier() {
private int nextInt = 0;
#Override public int getAsInt() { return nextInt++; }
}; // Works but is not functional.
}
#Test public void test_naive() {
int nextInt = 0;
IntSupplier supplier = () -> nextInt++; // Doesn't compile: requires nextInt to be final.
}
#Test public void test_nextIntIsFinal() {
final int nextInt = 0;
IntSupplier supplier = () -> nextInt++; // Doesn't compile: nextInt can't be incremented because it's final.
}
#Test public void test_useWrapper() {
final AtomicInteger nextInt = new AtomicInteger(0);
IntSupplier supplier = () -> nextInt.getAndIncrement(); // It is not the same as my original question as this test uses an extra object.
}
}
If the answer is simply that it cannot be done without using extra objects, please just say so.
Your definition of the problem is already non-functional. In functional you can't have different output without an argument. That's the definition. But how to create a sequence of numbers you can see in the java libraries: java.util.function.IntUnaryOperator. It's used like this:
IntStream.iterate(0, i -> i+1).limit(10).foreach(System.out::printLn);
you could do something like this:
IntSupplier supplier = new AtomicInteger(0)::incrementAndGet;
There is a standard way of working around this problem:
int[] nextInt = { 0 }; // optionally mark as final
IntSupplier supplier = () -> nextInt[0]++;
but it isn't really any more functional than the "Works but is not functional" solution.