I have the below code where I am lazy loading the instance creation of my class.
public class MyTest {
private static MyTest test = null;
private UniApp uniApp;
private MyTest(){
try{
uniApp = new UniApp("test","test123");
}
catch(Exception e){
e.printStackTrace();
logger.error("Exception " +e+ "occured while creating instance of uniApp");
}
}
public static MyTest getInstance(){
if (test == null){
synchronized(MyTest.class){
if (test == null){
test = new MyTest();
}
}
}
return test;
}
In the constructor, I am creating an instance of UniApp that requires passing userid, password in its own constructor. If lets say I pass a wrong userid, password of the uniApp object, uniApp doesn't get created. Here is what I need -
I am invoking the getInstance method in a different class -
MyTest test=MyTest.getInstance();
And here, I want to add condition if failure of creation of uniApp happens, do blah. How do I do that?
In general, if I am trying to invoke a method that throws an exception in class A in class B, and put a condition in B - if the method in class A throws exception, do this.
How can I achieve this? Let me know if my question is confusing. I can edit it :)
Throwing an exception from your private constructor would be ok (reference This SO question, or do some quick Googling). In your case, you are catching the exception thrown from new UniApp() and not passing it along - you can very easily pass that exception up the foodchain into your getInstance() method and then to whomever calls that singleton.
For instance, using your code:
private MyTest() throws UniAppException { // Better if you declare _which_ exception UniApp throws!
// If you want your own code to log what happens, keep the try/catch but rethrow it
try{
uniApp = new UniApp("test","test123");
}
catch(UniAppException e) {
e.printStackTrace();
logger.error("Exception " +e+ "occured while creating instance of uniApp");
throw e;
}
}
public static MyTest getInstance() throws UniAppException {
if (test == null) {
synchronized(MyTest.class) {
if (test == null) {
test = new MyTest();
}
}
}
return test;
}
To create your "if" condition to test whether the getInstance() method works or not, surround your call to getInstance() with a try/catch block:
...
MyTest myTest;
try {
myTest = MyTest.getInstance();
// do stuff with an instantiated myTest
catch (UniAppException e) {
// do stuff to handle e when myTest will be null
}
...
Since you haven't shown what actually calls MyTest.getInstance() I can't tell you what else to do besides that.
Related
If there is an exception which happens during the initialization of the class field, how would you catch it?
For instance:
class a{
int a = 1 / 0;
}
Here exception occurs at the field level.
I know that I could do:
class a {
a() {
try {
this.a = 1 / 0;
} catch (Throwable a) {}
}
int a;
}
But just out of curiosity, is it possible to do it while initializing the field?
Additional info: I am asking this because in my newest project I have one field which I want to initialize to the new instance of the object, and it would be cool to just write a = new Object(); but I can not since the constructor of that particular type throws the checked exception.
is it possible to do it while initializing the field?
You can define a method:
class a {
int a = aValue();
private int aValue() {
try
{
return 1/0;
}
catch (Throwable a){
// ...but now you need to return something, or (re)throw an exception.
}
}
}
or use an instance initializer:
class a {
int a;
{
try
{
this.a=1/0;
}
catch (Throwable a){
// You don't need to do anything here, unless `a` were `final`.
}
}
}
but note that instance initializers are inlined into the constructor (or, at least, any constructor that invokes super(...) explicitly or implicitly, rather than this(...)), so this is effectively the same as putting it in the constructor as in the question.
It's really hard to catch those. As a consequence, it is highly advisable to ensure that static initializers do not throw anything that one could feasibly want to catch. (e.g. throwing an OutOfMemoryError is fine, it's not likely someone would want to write code that catches this and does an alternative path or attempts to solve the problem).
This generally starts by replacing your static initializer with a method invocation. Replace:
static int a; static {a = 1/0; }
with:
static int a = calculateA();
private static int calculateA() {
return 1/0;
}
This is just a step along the path, of course. Move the initializing code (the calculateA method) to a separate class and now you can test it on its own, without even running into problem of catching exceptions thrown during static init of a class.
Once you've taken care of this, you can use this 'trick' to move the problem around. Imagine that the value of a is required for 2 of the methods in this class. Then, 'defer' the exception:
public class Example {
private static final int a;
private static final Throwable aProblem;
static {
int a = 0;
Throwable aProblem = null;
try {
a = calculateA();
} catch (RuntimeException e) {
aProblem = e;
}
Example.a = a;
Example.aProblem = aProblem;
}
private static int calculateA() { return 1/0; }
public static void apiMethodUsingA1() {
if (aProblem != null) throw aProblem;
return a;
}
public static void apiMethodUsingA2() {
if (aProblem != null) throw aProblem;
return a + 5;
}
}
If none of these options are available, for example because A is not written by you and cannot be changed, then you must delegate the A class as 'bad API / crappy library', and you do what you always do when you face such a library: Work around it, accept that you need to write hard to maintain / ugly code, and if it's really bad, write a wrapper to isolate the problems. Maybe even use reflection.
This is one guaranteed way to isolate the exception into a codeblock:
package com.foo;
class Example {
static int a = 1/0;
}
class Main {
public static void main(String[] args) throws Exception {
try {
Class<?> c = Class.forName("com.foo.Example");
} catch (ExceptionInInitializerError e) {
System.err.println("Hey I caught it");
Throwable actualException = e.getCause();
// do something with it here
actualException.printStackTrace(); // not this - this is for debugging only!
}
}
}
This is a contrived code example but based on a real world testing scenario from an Android project. It involves using class constructors to determine the validity of the class (ensure its in the correct state to be used). In this case just checking that the class constructor does not throw an exception before returning an instance of the class:
public class MyTestClass {
private MyTestClass() {
// Some code which might throw an exception
}
public static MyTestClass getInstance() {
if (tryClassConstructor(MyTestClass::new)) {
return new MyTestClass();
}
return null;
}
private static boolean tryClassConstructor(Runnable condition) {
try {
condition.run();
} catch (ArithmeticException ex) {
return false;
}
return true;
}
}
I understand that getInstance() is passing a constructor method reference (MyTestClass::new) to its tryClassConstructor() method, but that method expects... a Runnable. So does this mean class default constructors are by default Runnable?
You can do the following in a Runnable:
Runnable r = () -> {
new MyTestClass();
};
Note that isn't returning the instance of MyTestClass: it's simply invoking the constructor, and discarding the instance.
That's all MyTestClass::new does when you use it as a Runnable.
You can do this because MyTestClass::new is void-compatible. new MyTestClass() is a statement expression, so it can stand by itself as a statement.
In your example, the ´Runnable´ is equivalent to
Runnable r = () -> new MyTestClass();
You can refer to this article for more information ("Reference to a Constructor").
I am using Mockito services to test the Exception that could be thrown in MyFinalClass2 and be caught in MyAbstractClass as the concrete method makes a call to the getValue method in MyFinalClass2. This method returns an interface (MyInterfaceClass) object.
I asked a question earlier in Mocking Chained calls in Concrete Class Mockito and thankfully, the solution provided works when calling the getObject method found in MyFinalClass . Therefore, test1 works!
However, this time I have another final class (MyFinalClass2) which is not #Autowired, and is called after a call to a method in MyFinalClass. An Object of type MyFinalClass2 is return from the first call to method in MyFinalClass. When manually throwing a MyException2 in test2 , it does not get recognized and therefore causes an AssertionFailure in Test2 .
Also please note, the below line of code returns NULL as it has not yet been implemented. Which is the reason why I am returning in Test2 a new instance of MyFinalClass2 when this method is called.
MyFinalClass2 myFinalClass2 = getObject(strName);
Please see below code.
public abstract class MyAbstractClass{
#Autowired
private MyFinalClass myFinalClass;
//concrete method
protected MyInterfaceClass myConcreteMethod(String strName, String str)
{
try{
//returns null as it has not yet been implemented
MyFinalClass2 myFinalClass2 = getObject(strName);
MyInterfaceClass b = getValue(myFinalClass2,str);
return b;
} catch(MyException e){
LOGGER.log("ERROR THROWN" + e);
} catch(MyException2 e){
LOGGER.log("ERROR THROWN" + e);
}
}
public MyFinalClass2 getObject(String strName){
return myFinalClass.getObject(strName);
}
public MyInterfaceClass getValue(MyFinalClass2 myFinalClass2, String
str){
return myFinalClass2.getValue(str);
}
}
public final class MyFinalClass {
public MyFinalClass2 getObject(String strName) throws MyException{
**** HAS NOT YET BEEN IMPLEMENTED ****
return null;
}
}
public final class MyFinalClass2 {
public MyInterfaceClass getValue(String str) throws MyException2{
**** HAS NOT YET BEEN IMPLEMENTED ****
return null;
}
}
public interface MyInterfaceClass {
**** HAS NOT YET BEEN IMPLEMENTED BY ANY CLASS ****
void getStuff();
}
#ContextConfiguration(locations = "classpath:applicationContext-test.xml")
#RunWith(PowerMockRunner.class)
public class MyAbstractClassTest {
public static class ExampleConcreteClass extends MyAbstractClass{
}
#InjectMocks
#Spy
ExampleConcreteClass exampleConcreteClass;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
//THIS WORKS --- TEST 1
#Test
public void testIfExceptionOneIsThrown(){
try{
Mockito.when(exampleConcreteClass).getObject(name).
thenThrow(new MyException());
exampleConcreteClass.myConcreteMethod();
Assert.fail();
}catch(MyException e){
Assert.assertTrue(Boolean.TRUE);
}
}
//This test DOES NOT work --- TEST 2
#Test
public void testIfExceptionTwoIsThrown(){
try{
MyFinalClass2 myFinClass2 = new MyFinalClass2();
String strName = "name";
String str = "str";
Mockito.when(exampleConcreteClass).getValue(myFinClass2,str).
thenThrow(new MyException2());
Mockito.when(exampleConcreteClass).getObject(strName).
thenReturn(myFinClass2);
exampleConcreteClass.myConcreteMethod();
Assert.fail();
}catch(MyException e){
Assert.fail();
}catch(MyException2 e){
Assert.assertTrue(Boolean.TRUE);
}
}
}
Please help. Greatly Appreciated!
First of all, I am sorry to say so, but if you need to think that hard about testing, it's normally a sure sign that the code is bad. Anway, you don't need PowerMock there, since Mockito 2 is able to mock final classes already (you have to opt-in for that, though).
Also your test doesn't make any sense at all, since your exampleConcreteClass.myConcreteMethod() cannot throw a MyException2, because...
} catch(MyException2 e){
LOGGER.log("ERROR THROWN" + e);
}
...thus the MyException2 will never leave the scope of the method, but be transformed into a log message there and then be discarded. It will not leave the method, thus trying to assert it will not work. You would have something like throw e; there, too:
} catch(MyException2 e){
LOGGER.log("ERROR THROWN" + e);
throw e; // re-throw e, otherwise it ends here
}
Also, just as a hint, what you are trying to do there can be more easily done by simple writing...
#Test(expected=MyException2.class)
public void testIfExceptionTwoIsThrown() throws MyException, MyException2 {
...this way, you can remove all the try-catch stuff from your test method, since JUnit will automatically fail the test if no MyException2 is thrown. Alternatively, if you want to have more control, you can even have a look at JUnit's ExpectedException rule, which is a little bit more powerful and versatile than just the expected parameter (but that one should be enough for this case).
But of course, nothing changes the fact that, as long as your method catches your MyException2, it will not leave said method, so testing for it will not help.
I have a singleton class
public class SingletonText {
private static final CompositeText text = new CompositeText(new TextReader("text/text.txt").readFile());
public SingletonText() {}
public static CompositeText getInstance() {
return text;
}}
And TextReader constructor that could throw FileNameEception
public TextReader(String filename) throws FileNameException{
if(!filename.matches("[A-Za-z0-9]*\\.txt"))
throw new FileNameException("Wrong file name!");
file = new File(filename);
}
How can I rethrow it to main and catch it there?
Main class
public class TextRunner {
public static void main(String[] args) {
// write your code here
SingletonText.getInstance().parse();
System.out.println("Parsed text:\n");
SingletonText.getInstance().print();
System.out.println("\n\n(Var8)Task1:");
SortWords.sortWords(SingletonText.getInstance().getText().toString(), "^[AEIOUaeiou].*", new FirstLetterComparator());
System.out.println("\n\n(Var9)Task2:");
SortWords.sortWords(SingletonText.getInstance().getText().toString(), "^[A-Za-z].*", new LetterColComparator());
System.out.println("\n\n(Var16)Task3:");
String result = SubStringReplace.replace(SingletonText.getInstance()
.searchSentence(".*IfElseDemo.*"), 3, "EPAM");
System.out.println(result);
}}
Static block is executed only when class is loaded for the first time, so you can have something as below which will allow you to re-throw the exception. In you main method, you will surround getInstance() invocation in a try-catch block and then in catch you can do whatever you are looking for.
In case of exception, this exception will be thrown and re-thrown (from you static block) only once, at time of class loading. What #Alexander Pogrebnyak has said is also true.
Looking at the code you have provided, since you are always reading text/text.txt files so below approach will work. In case you are looking to read different files and then re-throwing exception then that becomes all together a different story, and you hadn't asked that part neither the code you have provided shows the same. In any case, if that's what you are looking for then:
you need to create a singleton object of your CompositeText class.
create a setter method will create an object TextReader class using the file name string passed.
that setter method will have the try-catch block, and in the catch block you will re-throw the exception so that you can catch again in main method.
P.S.: since static blocks are executed only once when class is loaded and class is loaded only once per JVM (until you have custom class loaders and overriding the behavior) so this ensures that this singleton is thread-safe.
Code:
public class SingletonText {
private static CompositeText text = null;
static{
try {
text = new CompositeText(new TextReader("text/text.txt").readFile());
} catch (FileNameException e) {
// TODO: re-throw whatever you want
}
}
public SingletonText() {}
public static CompositeText getInstance() {
return text;
}
}
try to lazy initialze the singleton.
something like this:
public class SingletonText {
private static CompositeText text;
public SingletonText() {
}
public static CompositeText getInstance() {
if (text ==null) {
text = new CompositeText(new TextReader("text/text.txt").readFile());
}
return text;
}
}
Also, you need to declare the constructor private, and if it multi-threaded application you need to synchronized the new statement with double check locking. see this in wiki:
https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
Enjoy..
You will get java.lang.ExceptionInInitializerError when your singleton static initializer will fail.
As a cause it will have your FileNameException.
If you don't do anything, default exception handler will print the whole stack trace to standard error.
This is my first post in Stackoverflow, so far I have been the active reader of this forum and I am posting my first question here.
This is regarding the EasyMock usage, I am a new user of EasyMock and in the following example code I am setting expectation for a collaborator method with the same object to be returned (doesn't matter whether it is same object or different object but the result is same) and I am resetting before going out of the test method. but when the second test is executed, the mocked method is returning null, I am not sure why is this happening.
If I run the methods
#RunWith(PowerMockRunner.class)
#PrepareForTest({CollaboratorWithMethod.class, ClassTobeTested.class})
public class TestClassTobeTested {
private TestId testId = new TestId();
#Test
public void testMethodtoBeTested() throws Exception{
CollaboratorWithMethod mockCollaborator = EasyMock.createMock(CollaboratorWithMethod.class);
PowerMock.expectNew(CollaboratorWithMethod.class).andReturn(mockCollaborator);
EasyMock.expect(mockCollaborator.testMethod("test")).andReturn(testId);
PowerMock.replay(CollaboratorWithMethod.class);
EasyMock.replay(mockCollaborator);
ClassTobeTested testObj = new ClassTobeTested();
try {
testObj.methodToBeTested();
} finally {
EasyMock.reset(mockCollaborator);
PowerMock.reset(CollaboratorWithMethod.class);
}
}
#Test
public void testMothedtoBeTestWithException() throws Exception {
CollaboratorWithMethod mockCollaborator = EasyMock.createMock(CollaboratorWithMethod.class);
PowerMock.expectNew(CollaboratorWithMethod.class).andReturn(mockCollaborator);
EasyMock.expect(mockCollaborator.testMethod("test")).andReturn(testId);
PowerMock.replay(CollaboratorWithMethod.class);
EasyMock.replay(mockCollaborator);
ClassTobeTested testObj = new ClassTobeTested();
try {
testObj.methodToBeTested();
} finally {
EasyMock.reset(mockCollaborator);
PowerMock.reset(CollaboratorWithMethod.class);
}
}
}
Here is my Collaborator class
public class CollaboratorWithMethod {
public TestId testMethod(String text) throws IllegalStateException {
if (text != null) {
return new TestId();
} else {
throw new IllegalStateException();
}
}
}
And here is my class under test
public class ClassTobeTested {
public static final CollaboratorWithMethod collaborator = new CollaboratorWithMethod();
public void methodToBeTested () throws IOException{
try {
TestId testid = collaborator.testMethod("test");
System.out.println("Testid returned "+ testid);
} catch (IllegalStateException e) {
throw new IOException();
}
}
}
I am looking for help from you guys to understand what exactly is happening here
The collaborator variable in class ClassTobeTested is final. The first test case initalizes the variable with mock object. The second test case cannot initialize the variable again. You set the expectation on the mock object created in second test case but actually the variable is still referring to the first mocked object.
Since you do not want to modify the class, you should set the mock reference once using #BeforeClass and make "mockCollaborator" a global variable so that you can use the reference in multiple test cases.