i have the ambitious goal to get 100% test coverage in cobertura. How can i achieve this on this code? There will never be an exception because the file is on the classpath. Can i remove files fropm classpath with junit?
try {
InputStreamReader reader = new InputStreamReader(WsdlSource.class.getClassLoader().getResourceAsStream("stringresources/stringresources.properties"), "UTF-8");
try {
p.load(reader);
} finally {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
First of all, to be able to test things right you have to learn what what loose coupling is and what Mock Objects are.
Basically, it is never a good idea to create an object with new because you create a hard dependency between the class InputStreamReader and your logic.
If your object p implements some kind of an interface, it would be good if you pass the instance of it from outside of your logic. Some implementations of Mock Objects also allow you to mock a class but I would not recommend that.
For example if you write your code like that:
public myMethod(SomeKindOfInterface p, InputStreamReader reader) {
try {
p.load(reader);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch(IOException e) {
//intentionally left blank, nothing could be done upon exception on closing
}
}
}
Then in your JUnit you could use Mockito to mock the IOException.
InputStreamReader reader = new InputStreamReader(WsdlSource.class.getClassLoader().getResourceAsStream("stringresources/stringresources.properties"), "UTF-8");
SomeKindOfInterface mock = Mockito.mock(SomeKindOfInterface.class);
Mockito.when(mock.load(reader)).thenThrow(new IOException());
myInstance.myMethod(mock, reader);
This way you would have your catch block covered.
Related
Android app, Having a function calling another function, that function may throw
static string SOME_DEFINE_1 = "some_define_1";
......
void myFunc() {
try {
HashMap<String, String> data = new HashMap<>();
data.put("key_1", SOME_DEFINE_1);
otherObject.func(data);
} catch (Throwable ex){
Log.e(TAG, "+++ exception from otherObject.func(), "+ ex.toString());
// do something
anotherFunc();
}
}
How to test the catch block is called when unit testing the myFunc?
It isn't clear in your example where otherObject comes from, but in general, to test the exception handling blocks you need code that will throw the exception. In this example, one way may be to mock the otherObject and then use thenThrow to cause it to throw an exception when the func(data) method is called. You could use a spy of the class you are testing and stub the anotherFunc method so you can replace it with something else and then verify if it was invoked for the conditions you expect to throw the exception.
These articles show the general approach:
https://www.baeldung.com/mockito-spy - (number 4)
https://www.baeldung.com/mockito-exceptions
So in a pseudo-code example:
// arrange
myClassUnderTest = spy(TheClassUnderTest);
otherObject = mock(OtherObject);
doNothing().when(myClassUnderTest).anotherFunc();
doThrow(new RuntimeException("simulated exception")).when(otherObject).func(any());
// act
myClassUnderTest.myFunc();
// assert
verify(myClassUnderTest , times(1)).anotherFunc();
Hello Liferay Experts,
I have a requirement where I need to stop an Admin from assigning a role, I am trying to implement this with a ModelListener.
Here is the code..
#Component(immediate = true, service = ModelListener.class)
public class TestUserModelListener extends BaseModelListener<User> {
#Override
public void onBeforeAddAssociation(Object classPK, String associationClassName, Objext accociationClassPK) throws ModelListenerException {
// ...
throw new ModelListenerException("User creation not allowed");
}
}
When this code executes, the exception is thrown but the UI doesnt handle it correctly, the control panel Menus are not displayed and the exception message is not displayed to the user.
How to throw an exception and handle it correctly in UI and display error message to the user.
Thanks
M
Andre Albert already gave you the correct hints in the comments.
You should keep the ModelListener and override the ActionCommand additionally.
First, read the tutorial about Overriding MVC Comands. When implementing your custom Command, use Liferay's implemenation as basis (don't forget to add the higher service.ranking) and replace the catch block with something like this:
// I took the freedom and refactored Liferay's catch block a little bit
catch (NoSuchUserException | PrincipalException e) {
SessionErrors.add(actionRequest, e.getClass());
actionResponse.setRenderParameter("mvcPath", "/error.jsp");
} catch (MembershipPolicyException e) {
SessionErrors.add(actionRequest, e.getClass(), e);
actionResponse.setRenderParameter("mvcPath", "/edit_user.jsp");
actionResponse.setRenderParameter("screenNavigationCategoryKey", UserFormConstants.CATEGORY_KEY_GENERAL);
actionResponse.setRenderParameter("screenNavigationEntryKey", UserFormConstants.ENTRY_KEY_ROLES);
} catch (ForbiddenRoleAssociationException e) {
// Here you can add a SessionError
// and set some render parameters
} catch (Exception e) {
throw e;
}
The ForbiddenRoleAssociationException does not exist yet. It's purpose is to distinguish this special case of a ModelListenerException from others which might not interest you. You'll have to implement it yourself. Just extend the ModelListenerException:
public class ForbiddenRoleAssociationException extends ModelListenerException {
// here might be some constructors
}
Now adjust your ModelListener so that it throws your new ForbiddenRoeAssociationException:
#Component(immediate = true, service = ModelListener.class)
public class TestUserModelListener extends BaseModelListener<User> {
#Override
public void onBeforeAddAssociation(Object classPK, String associationClassName, Objext accociationClassPK) throws ModelListenerException {
// ...
throw new ForbiddenRoleAssociationException(); // or any other constructor
}
}
This way you should be able to display error messages to admins (depending on your code in the catch block of the ForbiddenRoleAssociationException) and circumvent any other (programmatic) attempt to assign the Role as well.
I'm struggling to find out where my MessageWebSocket.OutputStream disposes.
WebsocketManager():
public WebsocketManager()
{
baseInit();
}
baseInit():
private void baseInit()
{
messageWebsocket = new MessageWebSocket();
}
connect():
public async void connect(string token, IEventAggregator eventAggregator, EvaLogger evaLogger)
{
try
{
messageWebsocket.SetRequestHeader("iPlanetDirectoryPro", token);
_eventAggregator = eventAggregator;
_evaLogger = evaLogger;
_localDataManager = new SqliteLocalDataManager(_evaLogger, _eventAggregator);
messageWebsocket.MessageReceived += OnMessageReceived;
messageWebsocket.Closed += OnClosed;
messageWebsocket.Control.MessageType = SocketMessageType.Utf8;
await messageWebsocket.ConnectAsync(WSURI);
}
catch (Exception e)
{
_evaLogger.Error(e.Message, e);
}
}
requestChats():
public async void requestChats()
{
DataWriter dataWriter = new DataWriter(messageWebsocket.OutputStream);
dataWriter.WriteString(WebsocketRequestFactory.Create(SocketEventsEnm.GET_CHATS));
await SendData(dataWriter);
}
sendTextMessage():
public async void sendTextMessage(long chatId, string message)
{
DataWriter dataWriter = new DataWriter(messageWebsocket.OutputStream);
dataWriter.WriteString(WebsocketRequestFactory.Create(SocketEventsEnm.MESSAGE_OUT, chatId, message));
await SendData(dataWriter);
}
SendData():
private async Task SendData(DataWriter dataWriter)
{
try
{
_evaLogger.Info("Trying to send data...");
await dataWriter.StoreAsync();
_evaLogger.Info("Data was sent");
}
catch (Exception e)
{
_evaLogger.Error(e.Message, e);
}
}
Everything is working as intended, I can call requestChats() without a problem, but when I call sendTextMessage(), I get an System.ObjectDisposedException. I could also call requestChats() instead of sendTextMessage(). But after I call one of these methods a second time, I will get System.ObjectDisposedException.
I am pretty sure that it's the MessageWebSocket.OutputStream which is disposed, but I don't know where it's getting disposed. But maybe it's a thing about threads and not about disposing?
If you need any additional information, just ask. I keep struggling for the whole day with this issue.
EDIT 1:
Still couldn't figure out the problem. Today I tried the following things:
Change MessageWebSocket to ClientWebSocket: Other exception but it means the same:
The WebSocket is in an invalid state ('Closed')
Use a session variable for the WebSocket. It didn't solve the problem either
I am grateful for every idea, even if it's just a very small one...
I was able to fix the problem. Before I send data, I was always creating a new DataWriter. Now I only create one DataWriter which gets initializied when I connect the WebSocket to the server.
I guess the problem was that when the datawriter got cleaned by the garbage collector, the outputstream got closed. Imo the datawriter shouldn't have that much power, but that's my only explanation.
I'm using asyncTask to download some files over the internet. This is the code I've written which works
downloadUrl task = new downloadUrl(url1,"jsonData1","/sdcard/appData/LocalJson/jsonData1",context);
task.execute();
downloadUrl task1 = new downloadUrl(url2,"jsonData2","/sdcard/appData/LocalJson/jsonData2",context);
task1.execute();
downloadUrl task2 = new downloadUrl(url3,"jsonData3","/sdcard/appData/LocalJson/jsonData3",context);
task2.execute();
downloadUrl task3 = new downloadUrl(url4,"jsonData4","/sdcard/appData/LocalJson/jsonData4",context);
task3.execute();
Now, the tasks run in parallel considering the UI-Thread but they run serialized between one another, which is time consuming. So instead I've tried to execute them on the executor But the thing is that this way I'm missing some files, meaning that when they run serialized I end up with 38 files downloaded while the run on the Executor I end up with 20. I'm pretty sure that is, because I messed up something in the multi-threading code So I'll post it that to:
#Override
protected String doInBackground(String... args) {
downloadAndStoreJson(url,targetFolder);
JSONObject jsonObj = loadJSONObject(pathForLoad);
try {
processJsonData(jsonObj);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "done";
}
#Override
protected void onPostExecute(String result) {
s(targetFolder+" Finished!");
++mutex;
progressBar.setProgress(25*mutex);
if(mutex==4){
mutex=0;
progressBar.setProgress(100);
progressBar.dismiss();
s(monuments.size());
Intent intent = new Intent (getApplicationContext(),NextClass.class);
intent.putExtra("monuments", monuments);
startActivity(intent);
}
}
private void downloadAndStoreJson(String url,String tag){
JSONParser jParser = new JSONParser();
JSONObject json = jParser.getJSONFromUrl(url);
String jsonString = json.toString();
byte[] jsonArray = jsonString.getBytes();
File fileToSaveJson = new File("/sdcard/appData/LocalJson/",tag);
BufferedOutputStream bos;
try {
bos = new BufferedOutputStream(new FileOutputStream(fileToSaveJson));
bos.write(jsonArray);
bos.flush();
bos.close();
} catch (FileNotFoundException e4) {
// TODO Auto-generated catch block
e4.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
jsonArray=null;
jParser=null;
System.gc();
}
}
private JSONObject loadJSONObject(String path){
JSONObject jsonObj = null;
File readFromJson = new File(path);
byte[] lala;
try {
lala= org.apache.commons.io.FileUtils.readFileToByteArray(readFromJson);
s("---------------"+lala.length);
String decoded = new String(lala, "UTF-8");
jsonObj = new JSONObject(decoded);
} catch (IOException e5) {
// TODO Auto-generated catch block
e5.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return jsonObj;
}
and processJsonData is a long method which parses the json files, creates objects and then stores them in an ArrayList, that's where a problem might exist.
You need to make sure your code is Reentrant, meaning it must be possible to run it by several threads at the same time. Or if some code is used to syncronize the execution between your threads you need to make sure it is synchronized.
Looking at your code I see that the mutex is a static variable, which you use to keep track of your threads. Make sure that the operation on the mutex is synchronized, just to keep it clean. But that will not cause you problem...
I dont see your error in this code-snippet, either I fail to see the problem or it might be located in some other methods? Can you please share "downloadAndStoreJson"?
I am having problem with this contact retrieving code. The function getContact() is retuning null.
private PIM pim;
private ContactList clist;
public ContactExtract(){
pim=PIM.getInstance();
try{
clist=(ContactList) pim.openPIMList(PIM.CONTACT_LIST,PIM.READ_ONLY);
}catch(Exception e){}
}
public Vector getContact(){
//ContactDetail cd[]= new ContactDetail[200];
Vector v=new Vector();
try{
Enumeration en=clist.items();
//String num=null;
//String temp[]=new String[2];
//int i=0;
while(en.hasMoreElements()){
Contact c=(Contact)en.nextElement();
v.addElement(c);
//temp=c.getStringArray(Contact.NAME, i);
//num=c.getString(Contact.TEL, i);
//cd[i]=new ContactDetail(temp[0],temp[1],num);
}
clist.close();
}catch(Exception e){}
return v;
Most likely reason for NPE you are getting is is that clist value is null in the getContact method. Most likely reason for this is, in turn, some exception that happens in ContactExtract() constructor.
But one would never know that for sure as long as you swallow exceptions. If you're interested, search the web for something like java swallow exceptions to learn in more details why this is bad.
Meanwhile, the most straightforward way to find out what happened is to add appropriate logging everywhere in your code, first of all in the catch blocks. Make sure there are no statements like catch(Exception e){} and your reward will be much easier understanding on what went wrong.
In constructor, replace empty catch block with something like:
catch(Exception e){
Sustem.out.println("exception in openPIMList: [" + e + "]");
}
In getContat method, do about the same, only with appropriate log message:
catch(Exception e){
Sustem.out.println("exception in getContact: [" + e + "]");
}
Then, re-run the code in emulator and look into its console to find out what went wrong.
Another thing worth adding in the code is checking, logging and handling for possible null values. In getContact() method, clist can be null and cause you all the kind of trouble but you don't even try to check and handle that.
Always try to print Exception e.
catch(Exception e)
{
e.printStackTrace();
}
You'll come to know what's wrong in the code.