My application use FastScanner
(based on BufferedReader
) to read input (Look at code section of my question).
If I want to substitute input in my tests I should mock up FastScanner
(Look at code section of my question).
Problem: For each input I should make separate mockup.
It'll be greate if I can switch input inside the single Mock Up.
Question: How to add custom methods to JMockit MockUps and than call them?
(Look at switchInput
method of FastScanner
mockup)
Code: [This section is optional, only for your better understanding]
FastScanner
protected static class FastScanner {
BufferedReader br;
StringTokenizer st;
FastScanner(InputStream f) {
br = new BufferedReader(new InputStreamReader(f));
}
String next() throws IOException {
while (st == null || !st.hasMoreTokens()) {
st = new StringTokenizer(br.readLine());
}
return st.nextToken();
}
int nextInt() throws IOException {
return Integer.parseInt(next());
}
}
FastScanner MockUp:
new MockUp<FastScanner>() {
private int[] input1 = new int[] {17, 2, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1};
private int[] input2 = new int[] {5, 2, 2, 3, 3, 3, 3, 3};
private int[] input3 = new int[] {8, 2, 5, 1, 3, 1, 1, 1, 1, 3, 1};
private byte toggler = 1;
private byte pointer = 0;
//HERE THE QUESTION: HOW CAN I CALL THIS METHOD
public void switchInput() {
toggler++;
pointer = 0;
}
@SuppressWarnings("unused")
int nextInt() throws IOException {
int[] input = null;
switch (toggler) {
case 1: input = input1; break;
case 2: input = input2; break;
case 3: input = input3; break;
}
return input[pointer++];
}
};
You can't have multiple instances of the same MockUp
subclass at the same time (each such mock-up would simply override the previous one when it got instantiated). Instead, add an Invocation
parameter to your @Mock
method, and then use the information it provides to distinguish between multiple data sets. For example:
@Test
public void testClientWithVariedDataFromFastScanners()
{
new MockUp<FastScanner>() {
// some data structure for test data
@Mock
int nextInt(Invocation inv) {
int idx = inv.getInvocationIndex();
FastScanner fs = inv.getInvokedInstance();
// Find the next value by using idx or fs as a lookup index
// into the data structures:
int i = ...
return i;
}
};
client.doSomethingUsingFastScanners();
}
Also, if you want to call whatever methods (including static
methods) on a mock-up subclass, just make it a named class rather than an anonymous one.