Get methods using Java Reflection Class - java

Hi guys im new to all this test automation stuff and trying to learn following a tutorial but im stuck trying to run this code.
I get an exception
Exception in thread "main" java.lang.NullPointerException
at executionEngine.DriverScript.execute_Actions(DriverScript.java:45)
at executionEngine.DriverScript.main(DriverScript.java:39)
dunno whats wrong as im following a tutorial so i assume everything should be working.
package executionEngine;
import java.lang.reflect.Method;
import config.ActionKeywords;
import utility.ExcelUtils;
public class DriverScript {
//This is a class object, declared as 'public static'
//So that it can be used outside the scope of main[] method
public static ActionKeywords actionKeywords;
public static String sActionKeyword;
//This is reflection class object, declared as 'public static'
//So that it can be used outside the scope of main[] method
public static Method method[];
//Here we are instantiating a new object of class 'ActionKeywords'
public DriverScript() throws NoSuchMethodException, SecurityException{
actionKeywords = new ActionKeywords();
//This will load all the methods of the class 'ActionKeywords' in it.
//It will be like array of method, use the break point here and do the watch
method = actionKeywords.getClass().getMethods();
}
public static void main(String[] args) throws Exception {
//Declaring the path of the Excel file with the name of the Excel file
String sPath = "D://Tools QA Projects//trunk//Hybrid Keyword Driven//src//dataEngine//DataEngine.xlsx";
//Here we are passing the Excel path and SheetName to connect with the Excel file
//This method was created in the last chapter of 'Set up Data Engine'
ExcelUtils.setExcelFile(sPath, "Test Steps");
//Hard coded values are used for Excel row & columns for now
//In later chapters we will use these hard coded value much efficiently
//This is the loop for reading the values of the column 3 (Action Keyword) row by row
//It means this loop will execute all the steps mentioned for the test case in Test Steps sheet
for (int iRow = 1;iRow <= 9;iRow++){
//This to get the value of column Action Keyword from the excel
sActionKeyword = ExcelUtils.getCellData(iRow, 3);
//A new separate method is created with the name 'execute_Actions'
//You will find this method below of the this test
//So this statement is doing nothing but calling that piece of code to execute
execute_Actions();
}
}
//This method contains the code to perform some action
//As it is completely different set of logic, which revolves around the action only,
//It makes sense to keep it separate from the main driver script
//This is to execute test step (Action)
private static void execute_Actions() throws Exception {
//This is a loop which will run for the number of actions in the Action Keyword class
//method variable contain all the method and method.length returns the total number of methods
for(int i = 0;i < method.length;i++){
//This is now comparing the method name with the ActionKeyword value got from excel
if(method[i].getName().equals(sActionKeyword)){
//In case of match found, it will execute the matched method
method[i].invoke(actionKeywords);
//Once any method is executed, this break statement will take the flow outside of for loop
break;
}
}
}
}

The problem is that you do never fill something into your method[] array. In the constructor, the array would be filled, but it is never called. Therefore, try calling the constructor inside the main method.
public static void main(String[] args) throws Exception {
new DriverScript();
...

In this line you need to change "Test Steps" to 'Sheet1' (or change the Excel sheet name to "Test Steps"):
ExcelUtils.setExcelFile(sPath, "Test Steps");

Related

Simple Unit test with Mocks keeps failing; mock object not being passed to class?

I have a simple Unit Test that is failing. Hopefully I can explain this in simple terms as I've been looking at it for hours and I see what the issue is, but I am not too familiar the underlying theory behind Mocks so I am a bit confused and cannot fix it. I will summarize the issue very quickly and then paste the code below.
Basically, in my test method called getAllValidModelsTest(), it uses a for loop to iterate thru enum values of object type DeviceModel. There are only 5: [EX3400_24P, EX4300_32F, EX4300_48MP, SRX_345, FAUX].
So inside the for loop, before the Assert statement (Junit), it makes a static method call to getDevice(deviceId) and it should from there return a Device object. The first line under the for loop in the getAllValidModelsTest() mocks the elementMock object to return the current model that is being iterated over in the DeviceModels[] array that was returned from the .values() call on the enums DeviceModel class.
So my issue is, when it jumps in the 2nd iteration in my for loop (counting from 1), the Assert fails , because the 0th element in the DeviceModel[] array is obviously EX4300_32F, but in the #Before setUp annotation it is being mocked to return EX3400_24P. But the weird thing is, under the for loop inside the getAllValidModelsTest() method, it is being overridden/mocked again to return to the current model that is being iterated through when .getModel is called on the elementMock object, so it should be returning the SAME value...
This is how the class SwitchDeviceFactoryTest.java is constructed (the class with the Unit Test):
#PowerMockIgnore({"javax.net.ssl.*"})
#RunWith(PowerMockRunner.class)
#PrepareForTest({DataGatewayFactory.class, SwitchConfig.class, RouterConfig.class})
public class SwitchDeviceFactoryTest {
String deviceId = "testdevice";
String ip = "1.1.1.1";
DataGateway dbMock = Mockito.mock(DataGateway.class);
SwitchConfig swConfigMock = PowerMockito.mock(SwitchConfig.class);
RouterConfig routerConfigMock = PowerMockito.mock(RouterConfig.class);
TransportDeviceSecretsInfo secrets = new TransportDeviceSecretsInfo();
TransportDeviceSecretsData secretsData = new TransportDeviceSecretsData("root","rootPw", "sshUser", "sshPass", "snmpAuthPass", "snmpPrivPass");
IElement elementMock = Mockito.mock(IElement.class);
ITransportDeviceSecretsCrud transportDeviceSecretsCrud = mock(ITransportDeviceSecretsCrud.class);
ISwitchConfigCrud switchConfigCrud = mock(ISwitchConfigCrud.class);
IRouterConfigCrud routerConfigCrud = mock(IRouterConfigCrud.class);
IElementCrud elementCrud = mock(IElementCrud.class);
This is my setUp method that runs before the test. The only variables that should be of importance are the elementMock object, specifically the one being mocked to return the EX3400_24P object:
#Before
public void setup() throws Exception {
secrets.setSecretsData(secretsData);
PowerMockito.mockStatic(DataGatewayFactory.class);
Mockito.when(DataGatewayFactory.getInstance()).thenReturn(dbMock);
Mockito.when(dbMock.getTransportDeviceSecretsCrud()).thenReturn(transportDeviceSecretsCrud);
Mockito.when(transportDeviceSecretsCrud.getServerSecretsInfo(anyString())).thenReturn(Optional.of(secrets));
Mockito.when(transportDeviceSecretsCrud.getReportedSecretsInfo(anyString())).thenReturn(Optional.of(secrets));
when(dbMock.getElementCrud()).thenReturn(elementCrud);
doReturn(Optional.of(elementMock)).when(elementCrud).getById(anyString());
Mockito.when(elementMock.getModel()).thenReturn(DeviceModel.EX3400_24P.getModel());
Mockito.when(elementMock.getType()).thenReturn(ElementType.SWITCH);
Mockito.when(dbMock.getSwitchConfigCrud()).thenReturn(switchConfigCrud);
Mockito.when(switchConfigCrud.get(anyString())).thenReturn(Optional.of(swConfigMock));
Mockito.when(swConfigMock.getIp()).thenReturn(ip);
Mockito.when(dbMock.getRouterConfigCrud()).thenReturn(routerConfigCrud);
Mockito.when(routerConfigCrud.get(anyString())).thenReturn(Optional.of(routerConfigMock));
Mockito.when(routerConfigMock.getIp()).thenReturn(ip);
And the test method:
#Test
public void getAllValidModelsTest() throws Exception {
for (DeviceModel model: DeviceModel.values()) {
when(elementMock.getModel()).thenReturn(model.getModel());
if (model == DeviceModel.SRX_345)
when(elementMock.getType()).thenReturn(ElementType.ROUTER);
else
when(elementMock.getType()).thenReturn(ElementType.SWITCH);
Device device = DeviceFactory.getDevice(deviceId);
assertEquals(model, device.getModel());
}
}
The thing that doesn't make sense, is I was refactoring code, and only changed 2 lines (the elementCrud and elementMock .doReturn and .when calls) and it works perfectly fine on the develop branch.
When I debug, I can see that on the 2nd iteration of the for loop, .getModel returns EX3400_24P object inside the static getDevice method, when it should be returning model.getModel() , which would be the 2nd object being iterated on in the .values() enum array of DeviceModels... so it should be EX4300_32F.
On the develop branch, this works perfectly.... It's as if the Mockito mock object forgets what it's suppose to do when it jumps inside the DeviceFactory class inside the getDevice method once its called in my getAllValidModelsTest() method (i.e. Device device = DeviceFactory.getDevice(deviceId);)
Here is the .getDevice method from the DeviceFactory class:
public static Device getDevice(String serialNumber) throws Exception {
IElement element = dataGateway.getElementCrud().getById(serialNumber).get();
DeviceModel model = DeviceModel.valueOfLabel(element.getModel()); // right here is where it returns the wrong model... it returns EX3400_24P on the 2nd iteration
log.info("Found device {} in database", serialNumber);
if (serialNumber.startsWith(FakeDevicePrefix.ATGTEST.toString()) || serialNumber.startsWith(FakeDevicePrefix.FAKE.toString())) {
log.info("Detected FAKE/ATG serial number. Using FAUX device.");
model = DeviceModel.FAUX;
}
switch (element.getType()) {
case SWITCH:
SwitchConfig config = dataGateway.getSwitchConfigCrud().get(serialNumber).get();
return getDevice(serialNumber, config.getIp(), model);
case ROUTER:
RouterConfig rconfig = dataGateway.getRouterConfigCrud().get(serialNumber).get();
return getDevice(serialNumber, rconfig.getIp(), DeviceModel.SRX_345);
case PTP:
default:
log.warn("Unsupported device type {}", element.getType().toString());
throw new Exception("Unsupported device type " + element.getType().toString());
}
}
I did indeed comment out/remove the piece of code that mocks it to return EX3400_24P in the setUp() method with #Before annotation , but the tests fails with a NULL POINTER EXCEPTION at this point.
How does the .getModel method know to return what I mocked it to return in the previous class (SwitchDeviceFactoryTest.java) before it jumps into the DeviceFactory.java class? How does it remember that if I'm not passing it in as a variable into the getDevice() method?
Do I need to use PowerMock or something because this is a static method? How does this change anything?
Please help!

JUnit Passing No arguments to main Method Java

I'm trying to test my main method (which should accept exactly one argument) for no arguments passed. Can't seem to understand what am I missing here to achieve that.The nature of my program is such that it reads input from a file, creates objects by passing parameters read from the file, and displays output.
Failure Message:
org.junit.ComparisonFailure: Expected :Please pass one argument
Actual :
Here's my Unit Test:
#Test
public void givenNoParameter_shouldAskForOne() throws IOException {
String[] args = {};
String output;
try (ByteArrayOutputStream bOutput = new ByteArrayOutputStream()) {
System.setOut(new PrintStream(bOutput));
Main.main(args);
bOutput.flush();
output = bOutput.toString();
}
String newLine = System.getProperty("line.separator");
String[] breakDownOutput = output.split(newLine);
assertEquals(1, breakDownOutput.length);
assertEquals("Please pass one argument", breakDownOutput[0]);
}
Main Method:
public static void main(String[] args) {
if(args.length == 1) {
DisplayOrder.setFilePath(args[0]);
DisplayOrder.display();
} else{
System.err.println("Please pass one argument");
}
}
I've realized I was using System.err.println() in my main. Changing that to System.out.println() fixed it.
Not showing your main method, my only guess is, that you do not write anything to "System.out" in your main, especially there is no System.out.println("Please pass one argument"); statement which is executed.
So, your unit test fails perfectly for a not expected value in "breakDownOutput[0]".
What you have to do is to make certain that the System.out.println("Please pass one argument"); is executed if no arguments were provided to your main.
Also check your class name Main.main(...) since there might be other Main classes imported which will never print out your expected values to System.out

Java chat room program

I have to display the current user into the gui, but it keep saying the the hashset is empty, this has been bugging me for hours. What is the easiest way to fix this? There might be a lot of un used code as i was testing things trying to make it work.
Client.java
public class Client {
Server.names();
}
Server.java
public class Server {
public static HashSet<String> names = new HashSet<String>();
public static void main(String[] args) throws Exception{
while(true){
name = in.readLine();
if(name == null){
return;
}
if(!names.contains(name)){
names.add(name);
break;
}
}
}
}
Your Q is a bit unclear, but if you want to get the HashSet, names from your Server class, you need to get the reference to it by calling Server.name, not Server.name() as it is not a method.
Now names will be empty until you populate it. To populate it you need to call code that will read user input and store it in names. In this case you can call the main method of Server (see this related Q here) but unless you really want that to be your main method of Server, I would recommend renaming the method to populateNames() or something similar.

Java Swing Components not working in public void main(String[]args) [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I'm running the main method by clicking a jButton in this class. First tried by using
public static void main(String[]args)
All the java swing components started to show non static variable cannot be referenced from static content errors. So I changed
public static void main(String[]args)
to
public void main(String[]args)
No errors shown for the swing components but expected result are not displaying in the jTextArea. IF i print the expected output in System.out.println, it shows correctly. What am I doing wrong here? This is how i trigger main() to run by clicking on jButton
jButton4.setText("Analyze");
jButton4.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
try{
TestTextRazor test = new TestTextRazor();
test.main(new String[0]);
}
catch (Exception e) {
e.printStackTrace();
}
}
});
This is my main()
public void main(String[] args) throws NetworkException, AnalysisException {
File textSRC = new File("MyText.txt");
String myTextCount = null;
BufferedReader myTextBr = null;
String check = "";
try {
String myTextCurrentLine;
myTextBr = new BufferedReader(new FileReader(textSRC));
while ((myTextCurrentLine = myTextBr.readLine()) != null) {
myTextCount = myTextCount + " " + myTextCurrentLine;
}
// Sample request, showcasing a couple of TextRazor features
String API_KEY = "7d5066bec76cb47f4eb4e557c60e9b979f9a748aacbdc5a44ef9375a";
TextRazor client = new TextRazor(API_KEY);
client.addExtractor("words");
client.addExtractor("entities");
client.addExtractor("entailments");
client.addExtractor("senses");
client.addExtractor("entity_companies");
String rules = "entity_companies(CompanyEntity) :- entity_type(CompanyEntity, 'Company').";
client.setRules(rules);
AnalyzedText response = client.analyze(myTextCount);
File file = new File("Hello1.txt");
// creates the file
file.createNewFile();
// creates a FileWriter Object
FileWriter writer = new FileWriter(file);
// Writes the content to the file
for (Sentence sentence : response.getResponse().getSentences()) {
for (Word word : sentence.getWords()) {
System.out.println("----------------");
System.out.println("Word: " + word.getLemma());
for (Entity entity : word.getEntities()) {
///System.out.println("Matched Entity: " + entity.getEntityId());
}
for (Sense sense: word.getSenses()) {
//System.out.println("Word sense: " + sense.getSynset() + " has score: " + sense.getScore());
}
}
}
// Use a custom rule to match 'Company' type entities
for (Custom custom : response.getResponse().getCustomAnnotations()) {
for (Custom.BoundVariable variable : custom.getContents()) {
if (null != variable.getEntityValue()) {
for (Entity entity : variable.getEntityValue()) {
String CompanyFound = ("Variable: " + variable.getKey() +"\n"+ "Value:" + entity.getEntityId());
System.out.println(CompanyFound);
jTextArea3.append(CompanyFound);
writer.write(CompanyFound);
writer.flush();
writer.close();
}
}
}
}
String ObjButtons[] = {"Yes","No"};
int PromptResult;
PromptResult = JOptionPane.showOptionDialog(null,"Completed Analysis!\nIs there any error in the Analysis?","Homonym Entity Extraction Application",JOptionPane.DEFAULT_OPTION,JOptionPane.WARNING_MESSAGE,null,ObjButtons,ObjButtons[1]);
//JOptionPane.getAlignmentX(Component.BOTTOM_ALIGNMENT);
if(PromptResult==JOptionPane.YES_OPTION)
{
System.out.println("YEs!!!!!");
jTextArea2.setEditable(true);
jTextArea3.setEditable(true);
jButton4.setEnabled(false);
jButton5.setEnabled(true);
}
else{
JOptionPane.showMessageDialog(null, "Completed Analysis!","Alert", 1);
System.out.println("No!!!!!!!!!!");
jTextArea2.setEditable(false);
jTextArea3.setEditable(false);
jButton4.setEnabled(false);
}
}catch (IOException ex) {
}
}
Please guide me.
Basically, the error is saying, you are trying to reference non-static variables from a static context.
Non-static variables (often referred to as instance variables or fields) require an instance of their parent class in order to have some kind referencing context.
Take a look at Understanding Instance and Class Members for more details.
Without much more of an example to go by, I would create a class constructor and move the contents of the main method to it.
I would then fix the main method to be static and create a new instance of the class from the main method...
The reason I would refrain from making Swing components static is it's way to easy to mix up you references and end up referencing something that isn't actually displayed on the screen...
Updated
Two things.
Make sure that the context of your main method is correct, that the UI components that you have created are not static and you are referencing them correctly.
Don't call the TestTextRazor class directly. This is just an example of how the API works. Take the time to understand it and incorporate into your own class(es) as required
Firs of all, what you need to understand is that a static method cannot access class fields or other methods that are non-static. So look at your code. The main has to be static as that is its natural signature, which must remain in tact as is. So all your class fields that you are trying to access in the main method, need to be static. Is this good practice? Absolutely not. You can browse through the Swing tutorial to pick up on good practices. I'm sure if you run through 20 examples, you'll pick up on a lot of good coding practices for Swing. Good Luck!
"I'm running the main method by clicking a jButton in this class"
One thing I noticed that you are doing complete wrong is trying to call the main method from inside your actionPerformed. The main method should never be called. The JVM using that method as an entry point for your program.
Another thing you have to understand is that a Swing program is event-driven. One button, should not run a complete program, unless it is a very small program.
I would consider creating methods for different tasks like
public String getSomethingFromFile(String filename) throws IOExceptions {
}
where you can call that method from an actionPerformed or something to append data to a text area.
Learn to use class members and initialize them in your constructor or some initialization method.
If you want everything that's going on the main method to be performed on a button click, put all that code in the actionPerformed , not in the main. A typical form of what goes inside the main is just something like this, where you just need to initialize your class to get the program running
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
JFrame frame = new JFrame();
frame.add(new MyGUIPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
where new MyGUIPanel() is an instance of your Main class
Another option is to create a method to perform all the tasks that are in the main like
public void performTextRazorTask() throws NetworkException, AnalysisException {
...
}
and just call that method from the actionPerformed
Again, I stress that you have a look at the tutorials I linked for better practices, as this site isn't really a tutorial site, I don't want to get into a tutorial type answer.
First of all you can not make main method as non static.
As per this line non static variable cannot be referenced from static content errors. make those variables as static

Custom Console nullPointerException when checking for existing text

i have created a custom console for a program. I have a method that adds a message to the console called toConsole this asks for the string where it checks and adds the time to the string. it then goes to my function addConsole which checks if existing text is present if so it will then add the pre-existing text to the new text, else it just puts the new text in. so here is the error. i may also point out that if i enter text manually on the consoles input text box it does not produce this error.
Exception in thread "main" java.lang.NullPointerException
at com.michael.tech.api.console.RunConsole.addConsole(RunConsole.java:188)
at com.michael.tech.api.console.RunConsole.toConsole(RunConsole.java:204)
at com.michael.tech.api.console.RunConsole.toConsole(RunConsole.java:223)
at com.michael.tech.api.testerFile.main(testerFile.java:25)
here is the addConsole method
private static void addConsole(String s){
console.setText( ( console.getText().isEmpty()) ? s : (console.getText() + "\n" + s) );
}
the toConsole method
public static void toConsole(String s, boolean timeStamp, boolean classPath, String className){
if(s.startsWith("/")){
doCommand(s);
return;
}
Time t = new Time();
t.getSYSPrint();
String time = "[" + t.toMilitary() + "] ";
if(EchoTime || timeStamp){
addConsole(time + s);
}
else if(classPath){
addConsole(className);
}
else{
addConsole(s);
}
}
and lastly the Main method in testerFile class
public static void main(String[] args) {
RunConsole.startConsole();
RunConsole.toConsole("test");
}
Thanks in advance for any help. I assume it is some small mistake i overlooked (I hope too).
EDIT:
paste bin to see line numbers
RunConsole class
http://pastebin.com/2yUAwQc5
testerFile class
http://pastebin.com/R5ViLekp
The problem is that the JTextArea console still has its default null value as it has not been instantiated. This is because there is no instance of RunConsole created — Instead, you are accessing the methods of this class in a static way:
RunConsole.startConsole();
RunConsole.toConsole("test");
Using static methods is poor design especially since your application needs to have state. Make all static methods in RunConsole instance methods and replace the above lines with:
RunConsole runConsole = new RunConsole();
runConsole.startConsole();
runConsole.toConsole("test");
Also, when you do this, don't forget to remove your instance created in startConsole, otherwise you will not see the initial message from toConsole. Change:
new RunConsole().setVisible(true);
to
setVisible(true);

Categories

Resources