Junit Test Java - java

Can someone please let me know how to write a Junit test for the if statement on the below method? Thanks
public String preGame() {
Scanner gameMode = new Scanner(System.in);
// Enforce player to select a valid game Option
while (!gameMode.hasNext("1") && !gameMode.hasNext("2") && !gameMode.hasNext("3")){
System.out.print(leftBorder + "Please enter a valid option (1,2,3)");
gameMode.next();
}
String gameOption = gameMode.next();
String optionMessage = null;
if (gameOption.equals("1")) {
optionMessage = "Human vs Human";
} else if (gameOption.equals("2")) {
optionMessage = "Human vs Computer";
} else if (gameOption.equals("3")) {
optionMessage = "Computer vs Computer";
}
System.out.println(leftBorder + "you've selected a game of " + optionMessage);
return gameOption;
}

While this is a bad design, as mentioned in comments above, the easiest way to test this code WITHOUT changing the source is to mock STDIN which is read by the Scanner in the method. The only part to remember is to change STDIN back after the test. This can be done with #Before and #After.
private InputStream realStdIn;
#Before
public void replaceStdIn(){
realStdIn = System.in;
}
#After
public void restoreStdIn(){
//after test put STDIN back as System.in
System.setIn(realStdIn);
}
Now our tests can set mock InputStream as our new STDIN
#Test
public void testGameMode1(){
InputStream in = new ByteArrayInputStream("1".getBytes());
System.setIn(in);
//now we can call preGame()
assertEquals("Human vs Human".equals(preGame());
}

In addition to dkatzel, if you want to test the output stream you can intercept that too. In stead of doing it in a #Before and #After you can also put the logic into a reusable JUnit Rule. Here's a rule I wrote that helps me test the System.out classes in this test.

Related

How do I run speech recognizer before all other tasks in Java, in such a way that only if the output contains begin, the program continues

I have a login page and a sign up page in my program.
I want to run it only if the user says begin.
These pages are called in the main method of my class, and I have a speech recognizer class.
I want the program to continue only when String output.contains("begin") == true
I tried putting the Class.main(args) in my if(output.contains("begin") == true)) case, there was an unhandled exception, and when i surrounded that section with try and catch, it didn't work.
I was told that Inheriting and implementing the classes from my API will work, but I'm not quite sure how to do it.
final Microphone mic = new Microphone(FLACFileWriter.FLAC);
GSpeechDuplex duplex = new GSpeechDuplex("AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw");
duplex.setLanguage("en");
duplex.addResponseListener(new GSpeechResponseListener() {
String old_text = "";
public void onResponse(GoogleResponse gr) {
String output = gr.getResponse();
if (gr.getResponse() == null) {
this.old_text = response.getText();
if (this.old_text.contains("(")) {
this.old_text = this.old_text.substring(0,
this.old_text.indexOf('('));
}
System.out.println("Paragraph Line Added");
this.old_text = ( response.getText() + "\n" );
this.old_text = this.old_text.replace(")", "").replace("( ", "");
response.setText(this.old_text);
}
if (output.contains("(")) {
output = output.substring(0, output.indexOf('('));
}
if (!gr.getOtherPossibleResponses().isEmpty()) {
output = output + " (" + (String)
gr.getOtherPossibleResponses().get(0) + ")";
}
response.setText("");
response.append(this.old_text);
response.append(output);
System.out.println(output);
if(output.contains("begin") == true){
duplex.stopSpeechRecognition();
mic.close();
Trying_Different_Languages t = new Trying_Different_Languages();
frame.dispose();
}
}
});
Expect The program to begin when i say begin but
It it doesn't begin when I say begin.
The try and catch statements just help in error free compilation.
In a program there should exist only 1 public static void main(String[] args) method. That is the indicator which tells you there starts the program.
Instead of calling the main method you should add a different method which do the stuff you want at a specific point.
So in detail it can look like that:
public class SomeClass {
public static void someMethodName() {
//some stuff you want to execute
}
}
So and where you want to execute the code:
...
SomeClass.someMethodName(); //executes the stuff you want.
In this case it would work if you create different methods which do exactly that you need to do at a specific point.

Java 8 Streams IO - Tests

I've written a simple class whose reading and writing files by using a single stream.
Now I want to test it by using JUnit test or something like that but I have no clue where to start with this because as u can see this is only one stream and text is immediately printing to a new file.
public class OneStreamIOFile {
public void fileReaderWriter(String fileReadPath, String filePrintName) {
try (Stream<String> streamReader = Files.lines(Paths.get(fileReadPath));
PrintWriter printWriter = new PrintWriter(filePrintName)) {
streamReader
.filter(line -> line.matches("[\\d\\s]+"))
.map(line -> Arrays.stream(line.trim().split("[\\s]+"))
.reduce((a, b) -> a + "+" + b).get() + "="
+ Arrays.stream(line.trim().split("[\\s]+"))
.mapToInt(Integer::valueOf).sum())
.forEachOrdered(printWriter::println);
} catch (IOException e) {
System.out.println("File not found");
e.printStackTrace();
}
}
}
Main class
public class Main {
public static void main(String[] args) {
String filePath = "src/test/java/resources/1000.txt";
String filePrintName = "resultStream.txt";
new OneStreamIOFile().fileReaderWriter(filePath, filePrintName);
}
}
Any idea how to deal with this?
A unit test has to focus on the behavior, not on implementation details.
The way you are using to read from a stream and write to another stream doesn't matter.
Here you have to focus on what you have as input and as ouput of the method under test.
In input, you have String fileReadPath representing the file where you read from and and in output you have String filePrintName, the file created by the method under test.
So to unit test OneStreamIOFile.fileReaderWriter(), create an input test file and create an expected output test file containing what you expect as the input test file is passed to the method.
Of course store them in your test folders.
In your test, pass their String representation to the method under test.
Then, assert that the file created by the method has the same content as the expected output file.
You can check if the file has written by using below code snippet.
public class Sample {
#Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
#Test
public void testFileReaderWriter() throws IOException, InterruptedException {
File file=temporaryFolder.newFile("sample.txt");
Date createdTime=new Date();
OneStreamIOFile options=new OneStreamIOFile();
Thread.sleep(1000);
options.fileReaderWriter(file.getAbsolutePath(),"hellow");
Date modifiedTime=new Date();
Assert.assertTrue(createdTime.getTime()<modifiedTime.getTime());
}
}
You have to give some time after creating the file and if you need to check content you can read files content and assert it.
TemporyFolder is a rule using to handle file operations in Junit.

How to return 1 String in case there are multiple IF statements

How can I return 1 value, in case I have some IF statements?
For example, when I choose Shopify, it calls a new method that allows me to type into console some need credentials and then append all typied data into 1 String and return that String(test) to Main class.
In case, I choose Bigcommerce, it calls pretty much the same method and append all needed credentials for Biggcomerce into 1 String(test2) as well. But in this case public String credentailsCollector() should return test2.
How can I do that? Thanks.
public class CartCredentialsCollector {
//it should return something like this:
//store_url=https://test.myshopify.com&apiKey=myapikey&apiPassword=myapipassword
public String credentailsCollector() throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Do you want to connect a new shopping cart ('yes'/'no')");
String newConnection = bufferedReader.readLine();
if (newConnection.equals("no")) {
bufferedReader.close();
} else {
System.out.println("Specify your shopping cart. It works with Shopify and Bigcommerce only");
String newShoppingCart = bufferedReader.readLine();
if (newShoppingCart.equals("Shopify")) {
ShopifyCredentialsHandler sch = new ShopifyCredentialsHandler();
String test = sch.shopifyCredentialsHandler();
}
else if (newShoppingCart.equals("Bigcommerce")) {
BigcommerceCredentialsHandler bch = new BigcommerceCredentialsHandler();
String test2 = bch.bigcommerceCredentialsHandler()
}
else {
System.out.println("This method works with Shopify and Bigcommerce. Try to connect a Shopify or Bigcommerce store.");
bufferedReader.close();
}
}
// Here I need to return test (in case I choose "Shopify") or test2 (in case I choose "Bigcommerce"). How can I do that?
}
}
You can use a method scope String variable and set the value of that instead of two different String variables. Something like this:
public class CartCredentialsCollector {
//it should return something like this:
//store_url=https://test.myshopify.com&apiKey=myapikey&apiPassword=myapipassword
public String credentailsCollector() throws IOException {
String test = null;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Do you want to connect a new shopping cart ('yes'/'no')");
String newConnection = bufferedReader.readLine();
if (newConnection.equals("no")) {
bufferedReader.close();
} else {
System.out.println("Specify your shopping cart. It works with Shopify and Bigcommerce only");
String newShoppingCart = bufferedReader.readLine();
if (newShoppingCart.equals("Shopify")) {
ShopifyCredentialsHandler sch = new ShopifyCredentialsHandler();
test = sch.shopifyCredentialsHandler();
}
else if (newShoppingCart.equals("Bigcommerce")) {
BigcommerceCredentialsHandler bch = new BigcommerceCredentialsHandler();
test = bch.bigcommerceCredentialsHandler()
}
else {
System.out.println("This method works with Shopify. Try to connect a Shopify store.");
bufferedReader.close();
}
}
return test;
// Here I need to return test (in case I choose "Shopify") or test2 (in case I choose "Bigcommerce"). How can I do that?
}
}
You should either declare test before your if statements or make multiple returns - one inside each if.
As you have realised, the reason you can't access the "test" or "test2" variables where you want to make your return is because both of them are out of scope at that point.
You need to either declare a String variable up top (before your first if statement) where the scope of the variable would extend through the entire credentialsCollector() method, or use multiple returns, putting each return in the same scope as your "test" and "test2" variables.

How to call a class that accepts command line arguments?

I am not a good programmer. In school, I learned MATLAB. So i have no idea what I am doing.
I am working with the ThingMagic M6 reader. They have their own API. I wanted to create my own application to read the program. I want to use a sample program that they have supplied (since my program doesn't seem to work). However, the supplied program only accepts command line arguments. How do i change it so I can pass arguments to it in my code.
This is the supplied code: (at the command line I input tmr://10.0.0.101)
/**
* Sample program that reads tags for a fixed period of time (500ms)
* and prints the tags found.
*/
// Import the API
package samples;
import com.thingmagic.*;
public class read
{
static void usage()
{
System.out.printf("Usage: demo reader-uri <command> [args]\n" +
" (URI: 'tmr:///COM1' or 'tmr://astra-2100d3/' " +
"or 'tmr:///dev/ttyS0')\n\n" +
"Available commands:\n");
System.exit(1);
}
public static void setTrace(Reader r, String args[])
{
if (args[0].toLowerCase().equals("on"))
{
r.addTransportListener(r.simpleTransportListener);
}
}
static class TagReadListener implements ReadListener
{
public void tagRead(Reader r, TagReadData t) {
System.out.println("Tag Read " + t);
}
}
public static void main(String argv[])
{
System.out.println(argv.getClass().toString());
// Program setup
TagFilter target;
Reader r;
int nextarg;
boolean trace;
r = null;
target = null;
trace = false;
nextarg = 0;
if (argv.length < 1)
usage();
if (argv[nextarg].equals("-v"))
{
trace = true;
nextarg++;
System.out.println("Trace");
}
// Create Reader object, connecting to physical device
try
{
TagReadData[] tagReads;
r = Reader.create(argv[nextarg]);
if (trace)
{
setTrace(r, new String[] {"on"});
}
r.connect();
if (Reader.Region.UNSPEC == (Reader.Region)r.paramGet("/reader/region/id"))
{
r.paramSet("/reader/region/id", Reader.Region.NA);
}
r.addReadListener(new TagReadListener() );
// Read tags
tagReads = r.read(500);
// Print tag reads
for (TagReadData tr : tagReads)
System.out.println(tr.toString());
// Shut down reader
r.destroy();
}
catch (ReaderException re)
{
System.out.println("Reader Exception : " + re.getMessage());
}
catch (Exception re)
{
System.out.println("Exception : " + re.getMessage());
}
}
}
This is me trying to use it: (arg comes from a JTextField)
String[] argv = new String[1];
argv[0] = arg;
readOnceApp(argv);
I have a feeling there is a really simple answer to this problem, I just can't figure it out. I searched the internet for a few days and read books, and still can't figure it out. Any help is appreciated. Thank You.
edit: readOnceApp is one method I wrote. It is basically just the main method of the supplied code. I can include it, if it will help. I just didn't want to post too much code.
If you want to call the "main" method of a class from another class, do it like this:
String [] args = new String [1];
args[0]= "some param";
readOnceApp.main(args);
This is making the assumption that "readOnceApp" is the name of your class. (BTW, you should follow the convention of using capitalized class names, e.g. ReadOnceApp).
Hope this helps.

Java, Junit - Capture the standard input / Output for use in a unit test [duplicate]

This question already has answers here:
JUnit test for System.out.println()
(14 answers)
Closed 8 years ago.
I'm writing integration tests using JUnit to automate the testing of a console based application. The application is homework but this part isn't the homework. I want to automate these tests to be more productive -- I don't want to have to go back and retest already tested parts of the application. (Standard reasons to use Unit tests)
Anyway, I can't figure out or find an article on capturing the output so that I can do assertEquals on it nor providing automated input. I don't care if the output/input goes to the console/output pane. I only need to have the test execute and verify the the output is what is expected given the input.
Anyone have an article or code to help out with this.
Use System.setOut() (and System.setErr()) to redirect the output to an arbitrary printstream - which can be one that you read from programmatically.
For example:
final ByteArrayOutputStream myOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(myOut));
// test stuff here...
final String standardOutput = myOut.toString();
The System class has methods setIn(), setOut() and setErr() that allow you to set the standard input, output and error streams, e.g. to a ByteArrayOutputStream that you can inspect at will.
Here is the solution in place of ByteArrayOutputStream. It does not add anything to the idea of System.setOut. Rather, I want to share the implementation that is better than capturing everything into ByteArrayOutputStream. I prefer to capture only selected information and let all log messages to appear in the console as they are logged rather than capturing everything into a balckbox (of which size?) for later processing.
/**
* Once started, std output is redirected to this thread.
* Thread redirects all data to the former system.out and
* captures some strings.*/
static abstract class OutputCaputre extends Thread {
// overrdie these methods for System.err
PrintStream getDownstream() { return System.out;}
void restoreDownstream() { System.setOut(downstream);}
// will be called for every line in the log
protected abstract void userFilter(String line);
final PrintStream downstream;
public final PipedInputStream pis;
private final PipedOutputStream pos;
OutputCaputre() throws IOException {
downstream = getDownstream();
pos = new PipedOutputStream();
pis = new PipedInputStream(pos);
System.setOut(new PrintStream(pos));
start();
}
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(pis));
// once output is resotred, we must terminate
while (true) {
String line = br.readLine();
if (line == null) {
return;
}
downstream.println(line);
userFilter(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void terminate() throws InterruptedException, IOException {
restoreDownstream(); // switch back to std
pos.close(); // there will be no more data - signal that
join(); // and wait until capture completes
}
};
Here is an example of using the class:
OutputCaputre outputCapture = new OutputCaputre() {
protected void userFilter(String line) {
downstream.println("Capture: " + line);
}
};
System.out.println("do you see me captured?");
// here is your test
outputCapture.terminate(); // finally, stop capturing

Categories

Resources