How is GUI code being invoked before my Scanner? - java

I'm having some trouble with getting input from the command line before opening a GUI window. I asked this question previously on Apple Exchange but was sent here after we determined it to be a Programming problem. Basically I'm running a Scanner to get user input before I open up a window but it starts the program, switching spaces on my Mac, and then I have to switch back to the workspace with the terminal in it to answer the question. Here's a link to the original question.
https://apple.stackexchange.com/questions/45058/lion-fullscreen-desktop-switching-quirk/45065#comment51527_45065
Here's the code I've tested with...
public class Client extends JFrame {
public static void main(String[]args) {
Scanner in = new Scanner(System.in);
System.out.printf("\nGive me a size for the screen: ");
String response = in.nextLine();
new Client(response);
}
public Client(String title) {
super(title);
super.setVisible(true);
}
}

Use invokeLater() to start the GUI after you get the input.
final String response = in.nextLine();
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Client(response);
}
});
Note that your example runs fine on my platform due to timing differences. Also consider using the args array to pass parameters, or ask the implementation, as shown in FullScreenTest
Addendum: Reading your other thread a little closer, you can use the following approach that launches a NamedFrame in a separate JVM.
package cli;
import java.awt.EventQueue;
import java.io.IOException;
import java.util.Scanner;
import javax.swing.JFrame;
/** #see https://stackoverflow.com/q/9832252/230513 */
public class CommandLineClient {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Give me a name for the screen: ");
final String response = in.nextLine();
try {
ProcessBuilder pb = new ProcessBuilder(
"java", "-cp", "build/classes", "cli.NamedFrame", response);
Process proc = pb.start();
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
}
}
class NamedFrame extends JFrame {
public NamedFrame(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationByPlatform(true);
setVisible(true);
}
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new NamedFrame(args[0]);
}
});
}
}

Code appears to be ok. Is there any class level stuff in Client that you haven't shown here (e.g. static members etc?)
The whole switching workspaces description in your link is an OS level thing NOT java specifically.
Is there options to the java command or something on mac you could use?

Related

JUnit5: How can I simulate input from System.in to test the following method? [duplicate]

I have a Java command-line program. I would like to create JUnit test case to be able to simulate System.in. Because when my program runs it will get into the while loop and waits for input from users. How do I simulate that in JUnit?
Thanks
It is technically possible to switch System.in, but in general, it would be more robust not to call it directly in your code, but add a layer of indirection so the input source is controlled from one point in your application. Exactly how you do that is an implementation detail - the suggestions of dependency injection are fine, but you don't necessarily need to introduce 3rd party frameworks; you could pass round an I/O context from the calling code, for example.
How to switch System.in:
String data = "Hello, World!\r\n";
InputStream stdin = System.in;
try {
System.setIn(new ByteArrayInputStream(data.getBytes()));
Scanner scanner = new Scanner(System.in);
System.out.println(scanner.nextLine());
} finally {
System.setIn(stdin);
}
Based on #McDowell's answer and another answer that shows how to test System.out, I would like to share my solution to give an input to a program and test its output.
As a reference, I use JUnit 4.12.
Let's say we have this program that simply replicates input to output:
import java.util.Scanner;
public class SimpleProgram {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print(scanner.next());
scanner.close();
}
}
To test it, we can use the following class:
import static org.junit.Assert.*;
import java.io.*;
import org.junit.*;
public class SimpleProgramTest {
private final InputStream systemIn = System.in;
private final PrintStream systemOut = System.out;
private ByteArrayInputStream testIn;
private ByteArrayOutputStream testOut;
#Before
public void setUpOutput() {
testOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(testOut));
}
private void provideInput(String data) {
testIn = new ByteArrayInputStream(data.getBytes());
System.setIn(testIn);
}
private String getOutput() {
return testOut.toString();
}
#After
public void restoreSystemInputOutput() {
System.setIn(systemIn);
System.setOut(systemOut);
}
#Test
public void testCase1() {
final String testString = "Hello!";
provideInput(testString);
SimpleProgram.main(new String[0]);
assertEquals(testString, getOutput());
}
}
I won't explain much, because I believe the code is readable and I cited my sources.
When JUnit runs testCase1(), it is going to call the helper methods in the order they appear:
setUpOutput(), because of the #Before annotation
provideInput(String data), called from testCase1()
getOutput(), called from testCase1()
restoreSystemInputOutput(), because of the #After annotation
I didn't test System.err because I didn't need it, but it should be easy to implement, similar to testing System.out.
There are a few ways to approach this. The most complete way is to pass in an InputStream while running the class under test which is a fake InputStream which passes simulated data to your class. You can look at a dependency injection framework (such as Google Guice) if you need to do this a lot in your code, but the simple way is:
public class MyClass {
private InputStream systemIn;
public MyClass() {
this(System.in);
}
public MyClass(InputStream in) {
systemIn = in;
}
}
Under test you would call the constructor that takes the input stream. You cloud even make that constructor package private and put the test in the same package, so that other code would not generally consider using it.
Try to refactor your code to use dependency injection. Instead of having your a method that uses System.in directly, have the method accept an InputStream as an argument. Then in your junit test, you'll be able to pass a test InputStream implementation in place of System.in.
You can write a clear test for the command line interface by using the TextFromStandardInputStream rule of the System Rules library.
public void MyTest {
#Rule
public final TextFromStandardInputStream systemInMock
= emptyStandardInputStream();
#Test
public void readTextFromStandardInputStream() {
systemInMock.provideLines("foo");
Scanner scanner = new Scanner(System.in);
assertEquals("foo", scanner.nextLine());
}
}
Full disclosure: I'm the author of that library.
You could create a custom InputStream and attach it to the System class
class FakeInputStream extends InputStream {
public int read() {
return -1;
}
}
And then use it with your Scanner
System.in = new FakeInputStream();
Before:
InputStream in = System.in;
...
Scanner scanner = new Scanner( in );
After:
InputStream in = new FakeInputStream();
...
Scanner scanner = new Scanner( in );
Although I think you should better to test how your class should work with the data read from the input stream and not really how it reads from there.
The problem with BufferedReader.readLine() is that it is a blocking method which waits for user input. It seems to me that you don't particularly want to simulate that (i.e. you want tests to be fast). But in a testing context it continually returns null at high speed during testing, which is irksome.
For a purist you can make the getInputLine below package-private, and mock it: easy-peezy.
String getInputLine() throws Exception {
return br.readLine();
}
... you'd have to make sure that you had a way of stopping (typically) a loop of user interaction with the app. You'd also have to cope with the fact that your "input lines" would always be the same until you somehow changed the doReturn of your mock: hardly typical of user input.
For a non-purist who wishes to make life easy for themselves (and produce readable tests) you could put all this stuff below in your app code:
private Deque<String> inputLinesDeque;
void setInputLines(List<String> inputLines) {
inputLinesDeque = new ArrayDeque<String>(inputLines);
}
private String getInputLine() throws Exception {
if (inputLinesDeque == null) {
// ... i.e. normal case, during app run: this is then a blocking method
return br.readLine();
}
String nextLine = null;
try {
nextLine = inputLinesDeque.pop();
} catch (NoSuchElementException e) {
// when the Deque runs dry the line returned is a "poison pill",
// signalling to the caller method that the input is finished
return "q";
}
return nextLine;
}
... in your test you might then go like this:
consoleHandler.setInputLines( Arrays.asList( new String[]{ "first input line", "second input line" }));
before triggering off the method in this "ConsoleHandler" class which needs input lines.
maybe like this (not tested):
InputStream save_in=System.in;final PipedOutputStream in = new PipedOutputStream(); System.setIn(new PipedInputStream(in));
in.write("text".getBytes("utf-8"));
System.setIn( save_in );
more parts:
//PrintStream save_out=System.out;final ByteArrayOutputStream out = new ByteArrayOutputStream();System.setOut(new PrintStream(out));
InputStream save_in=System.in;final PipedOutputStream in = new PipedOutputStream(); System.setIn(new PipedInputStream(in));
//start something that reads stdin probably in a new thread
// Thread thread=new Thread(new Runnable() {
// #Override
// public void run() {
// CoursesApiApp.main(new String[]{});
// }
// });
// thread.start();
//maybe wait or read the output
// for(int limit=0; limit<60 && not_ready ; limit++)
// {
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
in.write("text".getBytes("utf-8"));
System.setIn( save_in );
//System.setOut(save_out);
#Stefan Birkner, Thanks!
Modify Pom.xml
Ref:
https://stackoverflow.com/a/66127606/8317677
https://github.com/stefanbirkner/system-lambda/blob/master/pom.xml
https://github.com/stefanbirkner/system-lambda/blob/master/src/test/java/com/github/stefanbirkner/systemlambda/WithTextFromSystemInTest.java
<properties>
<system-lambda.version>1.2.1</system-lambda.version>
</properties>
<dependencies>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-lambda</artifactId>
<version>${system-lambda.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
Add function code
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class SimpleProgram003 {
public static void main(String[] args) {
try{
String c;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
do{
c = in.readLine();
System.out.println(c);
String d = c;
}while(!c.equals("q"));
}catch(Exception e){
System.out.println("catch Exception");
}
}
}
Add test code
import static com.github.stefanbirkner.systemlambda.SystemLambda.*;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Unit test for simple App. JUnit 4.x.
*/
public class SimpleProgram003Test {
private final InputStream systemIn = System.in;
private final PrintStream systemOut = System.out;
private ByteArrayInputStream testIn;
private ByteArrayOutputStream testOut;
#Before
public void setUpOutput() {
testOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(testOut));
}
private void setInput(String data) {
testIn = new ByteArrayInputStream(data.getBytes());
System.setIn(testIn);
}
private String getOutput() {
return testOut.toString();
}
#After
public void restoreSystemInputOutput() {
System.setIn(systemIn);
System.setOut(systemOut);
}
#Test
public void testCase1() {
final String testString = "Hello 1\nq\n";
setInput(testString);
SimpleProgram003.main(new String[0]);
// String a = getOutput();
assertEquals("Hello 1\r\nq\r\n", getOutput());
}
#Test // Multiply inputs
public void testCase2() throws Exception {
withTextFromSystemIn(
"Input1",
"Input2",
"q",
"Input3"
).execute(() -> {
SimpleProgram003.main(new String[0]);
// String a = getOutput();
assertEquals("Input1\r\nInput2\r\nq\r\n", getOutput());
});
}
}

Awaiting for message using discordJDA not working as intended

I'm currently working on my discord bot. One problem I encountered is that I'm not able to find out how to allow the bot to wait for a user reply after a message is sent.
I also have tried reading the git documentation regarding using RestAction over here: https://github.com/DV8FromTheWorld/JDA/wiki/7)-Using-RestAction but it seems it does not mention anything about implementing an "await" function similar to discord.js
I tried coding to mimic such an effect:
public class EventHandler extends ListenerAdapter {
private static final String PREFIX = "&";
public static String[] args;
public void sendMessage(String s, GuildMessageReceivedEvent event) {
event
.getChannel()
.sendMessage(s)
.queue();
}
public void onGuildMessageReceived (GuildMessageReceivedEvent event) {
args = event
.getMessage()
.getContentRaw()
.split(" ");
if (args[0].equalsIgnoreCase(PREFIX + "any_command")) {
sendMessage("Type hello!");
if (args[0].equalsIgnoreCase(PREFIX + "hello") {
sendMessage("hello there!");
}
}
}
}
Main class:
import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder;
public class Main {
public static void main(String[] args) throws Exception {
JDA jda = new JDABuilder(AccountType.BOT)
.setToken("token goes here")
.setAutoReconnect(true).build();
try {
jda.addEventListener(new EventHandler());
} catch (Exception e) {
e.printStackTrace();
}
}
}
This doesn't register the hello command typed after the prompt given. My best guess would be that the condition is never met since the original condition overrides the upcoming one (args[0] is already any_command)
Any help would be appreciated!
I'd suggest the EventWaiter from JDA-Utilities (https://github.com/JDA-Applications/JDA-Utilities/)
Taking a quick look at the source, looks like you'll need something like this
EventWaiter waiter = new EventWaiter();
// SO wouldn't let me insert new lines for some reason.
waiter.waitForEvent(GuildMessageReceivedEvent.class, (event) -> event.getMessage().getContentRaw().equalsIgnoreCase("hello"), (event) -> event.getChannel().sendMessage("hello!").queue()));

I/O using windowbuilder in eclipse for a java application

I've never used java windowbuilder before, however I'm trying to test it with my program which performs operations on sets. It's a Gradle project. I wrote all classes in the default package (I knew that it's discouraged just when I was finished). The program reads a line of operations on sets, parses it and prints the result and keeps doing that while there is a new line input from the user.
I'm trying to make a simple GUI for this program using windowbuilder but I can't figure out how to run the main class in the windowbuilder class and make it take input from a jtextfield and prints output.
My main looks like this:
public static void main(String[] argv) {
new Main().start();
}
private void start() {
hmap = new HashMap<IdentifierInterface, SetInterface<BigInteger>>();
Scanner in = new Scanner(System.in);
// While there is input, read line and parse it.
while (in.hasNextLine()) {
try {
String statement = in.nextLine();
if (statement.trim().isEmpty()) {
System.out.println("error, no statement");
} else {
Scanner statementScanner = new Scanner(statement);
readStatement(statementScanner);
}
} catch (APException e) {
System.out.printf("%s\n", e.getMessage());
}
}
}
I made a new windowbuilder class, with the buttons and text fields, but I got stuck on how to run my main inside the windowbuilder. Your help is appreciated. Thanks in advance.
Eclipse RCP applications are OSGi plug-ins; they do not have a main() method.
Instead your Main class should look like this:
package com.myplugin;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Main implements BundleActivator {
#Override
public void start(BundleContext bundleContext) throws Exception {
// Copy your start logic here
}
}
Then edit META-INF/MANIFEST.MF file and set for example
Bundle-Activator: com.myplugin.Main
This makes your Main class the activator of the plug-in: start() will be invoked at load.

How to write a junit test script?

I wrote a java code which is working but I have to write a Junit Test Script for it, but I do not have the experience yet. I tried several hours, but I can not understand how it works. So your help is very welcomed. Thanks in advance :) Do you have any tipps for me? :)
import java.awt.*;
import java.awt.event.*;
class MailBox extends Frame {
private boolean request;
private String message;
TextField tf1;
public MailBox() {
Dimension screenDim = getToolkit().getScreenSize();
Dimension frameDim = getPreferredSize();
setLocation((screenDim.width-frameDim.width)/2, (screenDim.heightframeDim.height)/2); addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
}
Panel myPanel = new Panel();
myPanel.setLayout(new FlowLayout());
Label label1 = new Label("Message: ");
Button button1 = new Button("Send");
button1.addActionListener(new button1AL());
tf1 = new TextField("", 20);
myPanel.add(label1);
myPanel.add(tf1);
myPanel.add(button1);
add(myPanel, BorderLayout.CENTER);
setTitle("Mailbox");
pack();
show();
}
public synchronized void storeMessage(String message){
while(request==true){
try{
wait();
}
catch(InterruptedException e){
}
}
request = true;
this.message = message;
notify();
}
public synchronized String retrieveMessage(){
while(request==false){
try{
wait();
}
catch(InterruptedException e){
}
}
request=false;
notify();
return message;
}
public static void main(String args[]) {
System.out.println("Starting Mailbox...");
MailBox MyMailBox = new MailBox();
Consumer c1 = new Consumer(MyMailBox);
Thread t1 = new Thread(c1);
t1.start();
}
class button1AL implements ActionListener{
public void actionPerformed(ActionEvent ae){
storeMessage(tf1.getText());
tf1.setText("");
}
}
}
I would say that in your case the program did not reach yet the level when it should be Unit tested. I don't see any reason why you need to test that some constructor works when it just initializes the fields of the class and also that the program prints something. I would not check that.
In the case when you get some error and this error might contain different error messages, it is a good idea to verify that the message is the same, but this is not your case. So, the main point is that your unit test should test business logic.
Consider this template:
#Test
public void testGoUntilTankIsEmpty() throws Exception {
// SETUP SUT
Car car = new Car();
car.fillFullTank();
car.setSpeed(80);
// EXERCISE
int distanceInKm = car.goUntilTankIsEmpty();
// VERIFY
Assert.assertEquals(800, distanceInKm);
}
In this case we exercise (test) specified method and expect that the result will be 800 based on our preliminary setup. If it is true your unit test will pass otherwise it will fail.
And remember that unit test should test only some unit, so some small piece of code, but actual functionality.
JUnit's work by testing the code you have written with either the expected output, or incorrect output if you want to test whether your error handling works.
In your case you'd just test against the expected string it outputs.
So a basic test for what you have would look something along the lines of...
import org.junit.Test;
import org.junit.Assert.assertEquals
public class BasicTest{
#Test
public void describeAnimalTest(){
AnimalNew animal = new AnimalNew("Dog", 10, "x");
assertEquals("Dog is on level 10 und is a type of x", animal.describeAnimal();
}
}

Pass String as params from one Java App to another

I'm trying to pass String as parameter from one Java Aplications to second as StartUp parameter
for example I have Aplications that must call start another Java Aplication (just contains only JOptionPane, JDialog or simple JFrame) before System.exit(0);, there I trying to send some descriptions from closing application to another,
these code is simulations what I tried that and in this form, code works correctly and displayed String into the JTextArea ...
import java.io.IOException;
import java.util.concurrent.*;
public class TestScheduler {
public static void main(String[] args) throws InterruptedException {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(true);
for (int i = 0; i < 10; i++) {
final int j = i;
System.out.println("assign : " + i);
ScheduledFuture<?> future = executor.schedule(new Runnable() {
#Override
public void run() {
System.out.println("run : " + j);
}
}, 2, TimeUnit.SECONDS);
}
System.out.println("executor.shutdown() ....");
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
try {
Process p = Runtime.getRuntime().exec("cmd /c start java -jar C:\\Dialog.jar 'Passed info'");
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println("System.exit(0) .....");
System.exit(0);
}
private TestScheduler() {
}
}
//
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
public class Main {
private static ArrayList<String> list = new ArrayList<String>();
public Main() {
JFrame frm = new JFrame();
JTextArea text = new JTextArea();
if (list.size() > 0) {
for (int i = 0; i < list.size(); ++i) {
text.append(list.get(i));
}
}
JScrollPane scroll = new JScrollPane(text,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.add(scroll, BorderLayout.CENTER);
frm.setLocation(150, 100);
frm.setSize(new Dimension(400, 300));
frm.setVisible(true);
}
public static void main(String[] args) {
if (args.length > 0) {
for (String s : args) {
list.add(s);
System.out.print(s + " ");
}
}
Main m = new Main();
}
}
my question :
EDIT1: if is there exist another way how to pass some value from one Java Aplication (there must be called System.exit(0);) to another Java Aplication, another way as I tried by using Process/ProcessBuilder
EDIT2: my crosspost http://forums.oracle.com/forums/thread.jspa?threadID=2229798&tstart=0
accepted answer from OTN
accepted answer by jverd on OTN
Yes, there are other ways. Is this way not meeting your needs?
There's another exec() signature that takes an array, where the first element is the command and the rest of the elements are its args. It may or may not be a varargs call. That would look something like this, although it might not work exactly as I have it.
exec("cmd", "/c", "start", "java", "-jar", "C:\Dialog.jar", "Passed info");
// OR
exec(new String[] {"cmd", "/c", "start", "java", "-jar", "C:\\Dialog.jar", "Passed info"});
You could put the information in a file that the second process reads.
You could store the information in a database that the second process queries.
You could have one process open a ServerSocket and the other connect to it and send the data that way.
You could use a higher-level messaging tool like JMS, Active MQ, etc.
You could use RMI.
You could use CORBA.
I'm sure there are other approaches as well.
I have no idea which approach is best suited to your needs. That's something you'll need to figure out, although if you can't decide, if you post more details about your requirements here, somebody may offer some advice.
Dude,
Read When runtime exec won't and get back to us if you're still stuck.
It's a good article. I'm guessing you've got "a problem with your parameter" ;-)
Cheers. Keith.

Categories

Resources