0
votes

If I have an SUT which handles an exception using a try/catch block, as follows:

public static void methodToBeTested() {
    ...
    try {
        desktop.browse(new URI("www.google.com"));
    } catch (IOException e) {
        //Display message to user and log out entry in app logs
    }
    ...
}

Question is that should I test the condition from my unit tests that the IOException is thrown? (The method under test launches a URI in the default browser)

If yes, since I am not throwing the exception from this method, how do i unit test this condition when the desktop.browse() threw an IOException?

Any thoughts or suggestions? I am using JMock

Thanks!

1
How will the message be displayed? You could check for that, or if "log out entry" has occurred. If a method doesn't throw an exception, you shouldn't have to test for the exception occuring. Although, if something occurs due to an error, you can always check for the results from the exception. I don't see where mocking fits into this questionVince

1 Answers

1
votes

Basically what you want to do is to mockup Desktop and whenever you send a browse message to it (no matter what URI is used), instead of hitting that URI, it should throw an IOException.

I have used Jmock long time ago. JMock as far as I remember, has some limitations, for exmaple it does not provide a mechanism for mocking static methods. And I am not sure how easy it is to mock your browser class in jmock world.

However it is almost trivial to test this using jmockit, which supports all sorts of fancy mocking mechanisms (including static references, singletons etc). (I am mentioning jmockit because no matter what your browse class is, jmockit can mock it.)

Below is an excerpt from an example from their website:

package jmockit.tutorial.domain;

import org.apache.commons.mail.*;
import jmockit.tutorial.persistence.*;

import org.junit.*;
import mockit.*;

public final class MyBusinessService_ExpectationsAPI_Test
{
   @Mocked(stubOutClassInitialization = true) final Database unused = null;
   @Mocked SimpleEmail anyEmail;

   @Test
   public void doBusinessOperationXyz() throws Exception
   {
      final EntityX data = new EntityX(5, "abc", "[email protected]");
      final EntityX existingItem = new EntityX(1, "AX5", "[email protected]");

      new Expectations() {{
(1)      Database.find(withSubstring("select"), any);
         result = existingItem; // automatically wrapped in a list of one item
      }};

      new MyBusinessService(data).doBusinessOperationXyz();

(2)   new Verifications() {{ Database.persist(data); }};
(4)   new Verifications() {{ email.send(); times = 1; }};
   }

   @Test(expected = EmailException.class)
   public void doBusinessOperationXyzWithInvalidEmailAddress() throws Exception
   {
      new Expectations() {{
(3)      email.addTo((String) withNotNull()); result = new EmailException();
      }};

      EntityX data = new EntityX(5, "abc", "[email protected]");
      new MyBusinessService(data).doBusinessOperationXyz();
   }
}

Above is the class under test and below is a the test which specifically tests (3) part of the above code. I think it is similar to what you are trying to do. Check it out please.

   @Test(expected = EmailException.class)
   public void doBusinessOperationXyzWithInvalidEmailAddress() throws Exception
   {
      new MockUp<Email>() {
         @Mock
(3)      Email addTo(String email) throws EmailException
         {
            assertNotNull(email);
            throw new EmailException();
         }
      };

      new MyBusinessService(data).doBusinessOperationXyz();
   }
}

If you want to stick to jmock, it is fine. But then you need to give us more info about Desktop class and its browse method so that we can think about what we can do in jmock world.