Understanding referencing other classes in java - null pointer exception - java

I'm struggling understanding how work with java objects from other objects. I have 3 simple classes:
1) environment object
public class Environment {
protected String envName;
public Environment(String envName){
this.envName = envName;
}
// get and set methods
public String getenvName(){
return envName;
}
public void setenvName(String envName){
this.envName = envName;
}
}
2) Class that will populate this object
public class FetchConfig {
Environment environment;
public FetchConfig() {
}
public void buildConfig() {
environment.setenvName("Steve");
}
}
3) A class with main method with will work with my Environment objects:
public class WorkWithEnvironment {
private FetchConfig config;
public static void main(String[] args) throws FileNotFoundException,
IOException {
WorkWithEnvironment w = new WorkWithEnvironment();
w.setupConfig();
w.readEnvNames();
}
private void setupConfig() throws FileNotFoundException, IOException {
config = new FetchConfig();
config.buildConfig();
}
private void readEnvNames() {
System.out.println("Environment name is: "
+ config.environment.getenvName());
}
}
But when I run it, I keep getting an NPE(NullPointerException) here -> environment.setenvName("Steve");

You've never told FetchConfig which Environment to use. I think you meant to have environment = new Environment(); or similar in FetchConfig's default constructor.
You could also initialize the variable environment with a similar line in the buildConfig method.

Your second class is trying to set values inside your Environment Class before instantiating it and so it is null when you try to assign a value to it.
public class FetchConfig {
Environment environment;
public FetchConfig() {
environment = new Environment(null);
}
public void buildConfig() {
environment.setenvName("Steve");
}

Related

How can I manage (or pass as an argument) my config json to start the testing of my vertx application?

I have a small vertx application with an AppLauncher class that extend of VertxCommandLauncher and I set a appConfig.json with the typical config parameters :
public class AppLauncher extends VertxCommandLauncher implements VertxLifecycleHooks {
public static void main(String[] args) {
new AppLauncher().dispatch(args);
}
#Override
public void afterConfigParsed(JsonObject config) {
AppConfig.INSTANCE.setConfig(config);
}
To run my application in my IDE I put in edit configuration my main class (Applauncher.java) and the arguments :
run io.vertx.covid.verticle.MainVerticle -conf../vertx-application/src/main/resources/appConfig.json
This is my test class:
#BeforeAll
static void deployVerticles(Vertx vertx, VertxTestContext testContext) {
vertx.deployVerticle(BaseVerticle.class.getName(),testContext
.succeeding(id->testContext.completeNow()));
}
This is my BaseVerticle class that all my verticles extends from:
public abstract class BaseVerticle extends AbstractVerticle {
public static String CONTEXT_PATH = AppConfig.INSTANCE.getConfig().getString(Constants.CONTEXT_PATH);
}
And this is my AppConfig class :
public enum AppConfig {
INSTANCE;
private JsonObject config;
public JsonObject getConfig() {
return config;
}
public void setConfig(JsonObject config) {
this.config = config;
}
}
Everything works, but if I would like to test it in a separete way then I deploy my verticles but I have a Nullpointer in the CONTEXT_PATH (BaseVerticle class) because the config (suppose to be taken from appConfig.json) is null.
I haven't found a way to pass the arguments with my appConfig.json or should I call to the main method passing the arguments?
I like to do something that is similar to profiles in my vertx application.
If you set an environment variable with the key vertx-config-path before the vertx instance is initialized, you can control where vertx's config retriever (you might need to add vert-config to your gradle/maven dependencies) gets the configuration from.
In your launcher, you can do something like the following, which will give you the ability to add profile based config files to your resources folder conf/config-%s.json where %s is the profile name:
public class CustomLauncher extends Launcher {
public static final String ACTIVE_PROFILE_PROPERTY = "APP_ACTIVE_PROFILE";
private static final CLI cli = CLI.create("main")
.addOption(new Option()
.setShortName("p")
.setLongName("profile")
);
public static void main(String[] args) {
initDefaults(Arrays.asList(args));
new CustomLauncher().dispatch(args);
}
public static void executeCommand(String cmd, String... args) {
initDefaults(Arrays.asList(args));
new CustomLauncher().execute(cmd, args);
}
public static void initDefaults(List<String> args) {
System.setProperty(LoggerFactory.LOGGER_DELEGATE_FACTORY_CLASS_NAME, SLF4JLogDelegateFactory.class.getName());
CommandLine parse = cli.parse(args);
String profile = parse.getOptionValue("p");
if (profile != null && !profile.isEmpty()) {
System.setProperty(ACTIVE_PROFILE_PROPERTY, profile);
System.setProperty("vertx-config-path", String.format("conf/config-%s.json", profile));
}
}
}
Then in your test, instead of relaying on vertx test extension to inject vertx for you, you can initialize it by yourself and control the profile (aka which config file to load) like the following:
private static Vertx vertx;
#BeforeAll
public static void deployVerticles(VertxTestContext testContext) {
CustomLauncher.initDefaults(Arrays.asList("--profile", "test"))
vertx = Vertx.vertx();
ConfigRetriever.create(vertx).getConfig(asyncResult -> {
if (asyncResult.succeeded()) {
JsonObject config = asyncResult.result();
DeploymentOptions deploymentOptions = new DeploymentOptions()
.setConfig(config);
vertx.deployVerticle(BaseVerticle.class.getName(), deploymentOptions);
} else {
// handle failure
}
});
}
Then when you run your application, instead of providing -conf, you can use -p or --profile
I also highly recommend to get familiar with vertx-config as you can also get env variables, k8s config maps, and much more.
EDIT: I also highly recommend to move to Kotlin if possible, makes the async-code much easier to handle in an imperative way (with Coroutines). It's very hard to deal with libraries like Vert.x in Java compared to languages like Kotlin.
I solved my problem creating a verticle with the config stuffs (vertx-config documentation), here is my verticle config class:
public class ConfigVerticle extends AbstractVerticle {
protected static Logger logger = LoggerFactory.getLogger(ConfigVerticle.class);
public static JsonObject config;
#Override
public void start() throws Exception {
ConfigStoreOptions fileStore = new ConfigStoreOptions()
.setType("file")
.setOptional(true)
.setConfig(new JsonObject().put("path", "conf/appConfig.json"));
ConfigStoreOptions sysPropsStore = new ConfigStoreOptions().setType("sys");
ConfigRetrieverOptions options = new ConfigRetrieverOptions().addStore(fileStore).addStore(sysPropsStore);
ConfigRetriever retriever = ConfigRetriever.create(vertx, options);
retriever.getConfig(ar -> {
if (ar.failed()) {
logger.info("Failed to retrieve config from appConfig.json");
} else {
config = ar.result();
vertx.deployVerticle(MainVerticle.class.getName(), new DeploymentOptions().setConfig(config));
}
});
}
}
And my MainVerticle.class I pass the new configuration like this:
public class MainVerticle extends AbstractVerticle {
#Override
public void start(){
vertx.deployVerticle(BackendVerticle.class.getName(), new DeploymentOptions().setConfig(config()));
}
}
Then, my simpleTests :
#ExtendWith(VertxExtension.class)
public class BaseCovidTest {
protected WebClient webClient;
#BeforeEach
void initWebClient(Vertx vertx){
webClient = WebClient.create(vertx);
}
#BeforeAll
static void deployVerticles(Vertx vertx, VertxTestContext vertxTestContext) {
vertx.deployVerticle(ConfigVerticle.class.getName() ,vertxTestContext
.succeeding(id-> {
try {
vertxTestContext.awaitCompletion(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
vertxTestContext.completeNow();
}));
}
}
And everything works, thanks #Tom that inspired me to fix it!

how to get variable of one class in another extended class

in below test script I want to pass value of suiteResult from class SuiteOneBase to class SuiteOneCaseOne .How can i do this. Suppose if I am getting suiteResult =true then i should get true in class SuiteOneCaseOne . But now everytime i am getting false only
First class
public class SuiteOneBase extends SuiteBase{
boolean suiteResult;
#BeforeSuite
public void checkSuiteToRun() throws IOException{
init();
//To set TestSuiteList.xls file's path In FilePath Variable.
FilePath = TestSuiteListExcel;
SheetName = "SuitesList";
SuiteName = "SuiteOne";
ToRunColumnName = "SuiteToRun";
suiteResult= SuiteUtility.checkToRunUtility(FilePath, SheetName,ToRunColumnName,SuiteName);
if(!suiteResult){
SuiteUtility.WriteResultUtility(FilePath, SheetName, "Skipped/Executed", SuiteName, "TestSuite Skipped");
throw new SkipException(SuiteName+"'s SuiteToRun Flag Is 'N' Or Blank. So Skipping Execution Of "+SuiteName);
}
SuiteUtility.WriteResultUtility(FilePath, SheetName, "Skipped/Executed", SuiteName, "TestSuite Executed");
}
}
Second Class
public class SuiteOneCaseOne extends SuiteOneBase{
#BeforeTest
public void checkCaseToRun() throws IOException{
System.out.println("suiteResult "+suiteResult );
if(!suiteResult){
if(!SuiteUtility.checkToRunUtility(FilePath, SheetName,ToRunColumnNameTestCase,TestCaseName)){
SuiteUtility.WriteResultUtility(FilePath, SheetName, "Pass/Fail/Skip", TestCaseName, "TESTCASE SKIP");
throw new SkipException(TestCaseName+"'s CaseToRun Flag Is 'N' Or Blank. So Skipping Execution Of "+TestCaseName);
}
}
TestDataToRun = SuiteUtility.checkToRunUtilityOfData(FilePath, TestCaseName, ToRunColumnNameTestData);
}
SuiteBase
package com.stta.TestSuiteBase;
import java.io.IOException;
import com.stta.utility.Read_XLS;
public class SuiteBase {
public static Read_XLS TestSuiteListExcel=null;
public static Read_XLS TestCaseListExcelOne=null;
public static Read_XLS TestCaseListExcelTwo=null;
public void init() throws IOException{
TestSuiteListExcel = new Read_XLS(System.getProperty("user.dir")+"\\src\\com\\stta\\ExcelFiles\\TestSuiteList.xls");
TestCaseListExcelOne = new Read_XLS(System.getProperty("user.dir")+"\\src\\com\\stta\\ExcelFiles\\SuiteOne.xls");
TestCaseListExcelTwo = new Read_XLS(System.getProperty("user.dir")+"\\src\\com\\stta\\ExcelFiles\\SuiteTwo.xls");
}
}
You can use ITestContext for that purpose:
public class SuiteOneBase extends SuiteBase {
#BeforeSuite
public void checkSuiteToRun(ITestContext context) throws IOException {
// [...]
boolean suiteResult = SuiteUtility.checkToRunUtility(FilePath, SheetName,ToRunColumnName,SuiteName);
// [...]
context.setAttribute("suiteResult", suiteResult);
}
}
And
public class SuiteOneCaseOne extends SuiteOneBase {
#BeforeTest
public void checkCaseToRun(ITestContext context) throws IOException {
boolean suiteResult = context.getAttribute("suiteResult");
System.out.println("suiteResult "+suiteResult );
// [...]
}
}
You should create suiteResult public or protected variable of class SuiteOneBase
public boolean suiteResult;
or
protected boolean suiteResult;
Hope this will work!!
SuiteOneCaseOne extends SuiteOneBase and is in the same package, so it can already see the package-level suiteResult. No need for any additional passing.
The #BeforeSuite in SuiteOneBase runs before the #BeforeTest in SuiteOneCaseOne, so the fact that the latter sees suiteResult == false proves that the former - which must have run - must have explicitly set suiteResult = false.
You're not looking at a default value, or the value of a different field. checkSuiteToRun() must run, and there are no exceptions or returns, so:
suiteResult= SuiteUtility.checkToRunUtility(FilePath, SheetName,ToRunColumnName,SuiteName);
... must have returned false.
(And yet you don't mention the tests failing to run as a result of the SkipException. I don't know how that can be avoided. Unless perhaps your #BeforeSuite has been imported from the wrong package, i.e. it doesn't actually get run.)

Android - can't store a list in the Application class instance

I'm trying to store a list in the Application class instance as a global variable in one of my Android applications. Below is my Application class code:
public class DefectsApplication extends Application{
private NormalUser normalUser;
private ArrayList<Complaint> complaintList;
public String getTestString() {
return testString;
}
public void setTestString(String testString) {
this.testString = testString;
}
private String testString;
public NormalUser getNormalUser() {
return normalUser;
}
public void setNormalUser(NormalUser normalUser) {
this.normalUser = normalUser;
}
public ArrayList<Complaint> getComplaintList() {
return complaintList;
}
public void setComplaintList(ArrayList<Complaint> m_complaints) {
this.complaintList = complaintList;
}
}
Below is my code which is trying to access the fields from the Application class instance:
DefectsApplication defectsApplication = ((DefectsApplication)getApplicationContext());
defectsApplication.setComplaintList(m_complaints);
defectsApplication.setTestString("urghhhhhhhhh");
ArrayList<Complaint> complaintList = defectsApplication.getComplaintList();
String s = defectsApplication.getTestString();
In the above code, m_complaints is a list of objects. When I try to store a String, it works. But for a list, it doesn't. Please, help me to resolve this issue.
Probably, a typo is taking place:
public void setComplaintList(ArrayList<Complaint> m_complaints) {
this.complaintList = complaintList;
}
You're setting this.complaintList to itself which is initially null. Try
public void setComplaintList(ArrayList<Complaint> m_complaints) {
this.complaintList = m_complaints;
}

error: local variable is accessed from within inner class; needs to be declared final

When compiling the following code, i got compile error:
MadScientist.java:27: Error: local variable timeTraveler is accessed from within inner class; needs to be declared final
import java.util.*;
interface TimeTravelCallback {
void leaped(int amount);
}
interface TimeTraveler {
void adjust(int amount);
}
class LinearTimeTraveler implements TimeTraveler {
#Override public void adjust(int amount) {
}
}
public class MadScientist {
public static void main(String[] args) {
MadScientist madScientist = new MadScientist();
TimeTraveler linearTimeTraveler = new LinearTimeTraveler();
madScientist.experiment(linearTimeTraveler);
}
public void experiment(TimeTraveler timeTraveler) {
TimeTravelCallback cb = new TimeTravelCallback() {
#Override public void leaped(int amount) {
timeTraveler.adjust(amount); //error message
}
};
cb.leaped(20);
}
}
If I change
public void experiment(TimeTraveler timeTraveler) {
to
public void experiment(final TimeTraveler timeTraveler) {
then it works.
Is there any other fix without adding the 'final' at the method parameter?
If you want to do any operation on your final variable passed to your method then use any collection api like List.
public void experiment(final List<TimeTraveler> timeTraveler) {
}
Now, you can modify the value inside your list.
If you don't want to add final, you should create a constructor in you inner class TimeTravelCallback and pass the timeTraveler object to this constructor :
TimeTravelCallback cb = new TimeTravelCallback(timeTraveler) {
public TimeTravelCallback(TimeTraveler timeTraveler){
this.timeTraveler = timeTraveler;
}
#Override public void leaped(int amount) {
timeTraveler.adjust(amount); //error message
}
};

How to abstract Robotium Setup to run multiple test files

In a Blackbox test environment I would need to include CODE 1 and end with CODE 2 to perform a test by running Android JUnit Test (as explained from the Robotium site):
CODE 1:
public class ConnectApp extends ActivityInstrumentationTestCase2 {
private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME="com.example.android.notepad.NotesList";
private static Class<?> launcherActivityClass;
private Solo solo;
static {
try { launcherActivityClass=Class.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME); }
catch (ClassNotFoundException e) { throw new RuntimeException(e); }
}
public ConnectApp() throws ClassNotFoundException {
super(launcherActivityClass);
}
public void setUp() throws Exception {
this.solo = new Solo(getInstrumentation(), getActivity());
}
CODE 2:
public void testNumberOne() { … }
public void testNumberTwo() { … }
}
However, I would like to abstract CODE 1 of the code ( which includes getInstrumentation() and getAcitvity()) so that I can simply call them in a separate test file and then run CODE 2 . This is because I want to have tests in separate files and don't want to keep adding the same amount of CODE 1 code but just call a method/constructor to initiate the process.
Is there a way to do this? Thank you in advance.
yes there is a way to do this. What you will need to do is create an empty test class such as:
public class TestTemplate extends ActivityInstrumentationTestCase2 {
private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME="com.example.android.notepad.NotesList";
private static Class<?> launcherActivityClass;
private Solo solo;
static {
try { launcherActivityClass=Class.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME); }
catch (ClassNotFoundException e) { throw new RuntimeException(e); }
}
public ConnectApp() throws ClassNotFoundException {
super(launcherActivityClass);
}
public void setUp() throws Exception {
super.setUp();//I added this line in, you need it otherwise things might go wrong
this.solo = new Solo(getInstrumentation(), getActivity());
}
public Solo getSolo(){
return solo;
}
}
Then for every test class you want in the future instead of extending ActivityInstrumentationTestCase2 you will extend TestTemplate.
for example:
public class ActualTest extends TestTemplate {
public ActualTest() throws ClassNotFoundException {
super();
}
public void setUp() throws Exception {
super.setUp();
//anything specific to setting up for this test
}
public void testNumberOne() { … }
public void testNumberTwo() { … }
}

Categories