Android File manipulation tests with JUNIT - java

I am trying to test file manipulation with my APP. First of all I wanna check that whenever I call a function that reads the file, this function will throw an Exception because the file isn't there.
However, I don't seem to understand how to achieve this... This is the code I designed, but it doesn't run ... the normal JUNIT says the FILEPATH wasn't found, the android JUNIT says, the Test could not be run.
The folder: /data/data/example.triage/files/ is already available in the virtual device...
#Before
public void setUp() throws Exception {
dr = new DataReader();
dw = new DataWriter();
DefaultValues.file_path_folder = "/data/data/example.triage/files/";
}
#After
public void tearDown() throws Exception {
dr = null;
dw = null;
// Remove the patients file we may create in a test.
dr.removeFile(DefaultValues.patients_file_path);
}
#Test
public void readHealthCardsNonExistentPatientsFile() {
try {
List<String> healthcards = dr.getHealthCardsofPatients();
fail("The method didn't generate an Exception when the file wasn't found.");
} catch (Exception e) {
assertTrue(e.getClass().equals(FileNotFoundException.class));
}
}

It doesn't look like you are checking for the exception in a way that correlates with the JUnit API.
Have you tried to make the call:
#Test (expected = Exception.class)
public void tearDown() {
// code that throws an exception
}
I don't think you want the setup() function to be able to generate an exception, since it is called before all other test cases.
Here's another way to test exceptions:
Exception occurred = null;
try
{
// Some action that is intended to produce an exception
}
catch (Exception exception)
{
occurred = exception;
}
assertNotNull(occurred);
assertTrue(occurred instanceof /* desired exception type */);
assertEquals(/* expected message */, occurred.getMessage());
So I would make you setup() code not throw an exception and move the exception generating code to a test method, using an appropriate way to test for it.

Related

Performing assertion after exception using EasyMock

How can I test assertion immediately following an exception with EasyMock?
For example, there is a method storeIntoFile() which retrieves an object and writes it into a file. In case of an exception, this file is deleted. I'm looking to test this method specifically to verify that the file gets deleted on encountering an exception.
I have the following test to do this:
#Test (expected IOException.class)
public void testConnectionFailure throws IOException {
File storeFile = File.createTempFile(
"test",
"test"
);
storeIntoFile(storeFile);
Assert.assertFalse(storeFile.exists());
}
However in this case, the test completes as soon as the exception is encountered during the storeIntoFile call and does not proceed to test the following assertion. How can I test this assertion after the exception without using mock objects?
It's more a JUnit question than EasyMock. With JUnit 4.13, you can do the following.
public class MyTest {
public interface FileRepository {
void store(File file) throws IOException;
}
private void storeIntoFile(File file) throws IOException {
try {
repository.store(file);
} catch(IOException e) {
file.delete();
throw e;
}
}
private final FileRepository repository = mock(FileRepository.class);
#Test
public void testConnectionFailure() throws IOException {
File storeFile = File.createTempFile("test", "test");
IOException expected = new IOException("the exception");
repository.store(storeFile);
expectLastCall().andThrow(expected);
replay(repository);
IOException actual = assertThrows(IOException.class, () -> storeIntoFile(storeFile));
assertSame(expected, actual);
assertFalse(storeFile.exists());
}
}
I do not recommend the expected exceptions. assertThrows is much better since it allows to assert on the exception.

How do you assert that an exception is thrown if it has already been consumed/handled/caught

Let's say I test a class method that is reliant on another method that we do not want or can not test directly, which handles a checked exception, in the following manner:
public class A {
public void process(){
if (isProcessingSuccessful()){
LOG.info("Success");
}
else {
LOG.error("Fail");
}
}
private boolean isProcessingSuccessful(){
try{
doSomeOtherStuff();
return true;
}
catch (Exception e){
return false;
}
}
}
Now, if I have a test class testing for the A#process(), like:
#Test
public void shouldFailDueToCommandGatewayError() {
A a = new A();
// setting up preconditions
//testing here
a.process();
//Now, assert exception was thrown during the course of a.process() execution, something like
exception.expect(NullPointerException.class);
// ?? how to do that?
}
TLTD: It is possible to write separate test for isProcessingSuccessful() or do something similar, but let's say that method is not accessible for testing, like it's private in a library?
Given the above constraints, is there any way to write a test in a way that ascertains the exception was thrown in the underlying method as above?
No, junit can't tell the exception was thrown, since it gets eaten by the code being tested. For you to detect what happened here you would have to check what was written to the log. Replace the appender with something that holds onto what is written to it, then the test can verify what was written to it at the end of the test.
You can't catch the exception again which have been already consumed. The only way is to catch the exception with the test method as described below.
Annote the test method that is supposed to fail with #Test and use the expected parameter for the expected exception.
#Test(expected = NullPointerException.class)
public void shouldFailDueToCommandGatewayError() {
// something that throws NullPointerException
}
#Test(expected = NullPointerException.class)
This basically says:
If this test quits with a NullPointerException then everything is as expected. Otherwise this test will fail.
#Test(expected = NullPointerException.class)
has been mentioned already. This feature came wuth JUnit 4. Before that and if you want to do want to check more than just a particular type of exception being thrown, you can do something like this:
try {
doSometing("", "");
fail("exception expected");
}
catch(IllegalArgumentException iae) {
assertEquals("check message", "parameter a must not be empty", iae.getMessage());
assertNull("check non-existance of cause", iae.getCause());
}
try {
doSometing("someval", "");
fail("exception expected");
}
catch(IllegalArgumentException iae) {
assertEquals("check message", "parameter b must not be empty", iae.getMessage());
assertNull("check non-existance of cause", iae.getCause());
}
This is particular useful if the same type of exception is thrown and you want to ensure that the "correct" exception is thrown with a given combination of parameters.

How to check multiple exceptions with one JUnit Method?

i have this code in my program which is needed to be tested with jUnit
void deleteCustomer(String name) throws UnknownCustomerException,
AccountNotEmptyException {
if (name == null) {
throw new NullPointerException();
} else if (!exists(name)) {
throw new UnknownCustomerException();
} else if (getCustomer(name).deletable()) {
customerList.remove(getCustomer(name));
}
}
I thought i can test it in one JUnit method like
#Test
public void createCustomer(){
System.out.println("createCustomerTest");
try {
element.createCustomer(null);
//fail("Expected an IndexOutOfBoundsException to be thrown");
} catch (NullPointerException anIndexOutOfBoundsException) {
assertTrue(anIndexOutOfBoundsException.getMessage().equals("NullPointerException"));
}
}
As you can see I already tried unsuccessfully to implement the NPE.
How can I check for several Exceptions in one JUnit Method? I checked some How-To's in the web but failed with that too.
I think in your case you should have separate tests, however you can achieve this like so if using Java 8:
Using an AssertJ 3 assertion, which can be used alongside JUnit:
import static org.assertj.core.api.Assertions.*;
#Test
public void test() {
Element element = new Element();
assertThatThrownBy(() -> element.createCustomer(null))
.isInstanceOf(NullPointerException.class)
.hasMessageContaining("NullPointerException");
assertThatThrownBy(() -> element.get(1))
.isInstanceOf(IndexOutOfBoundsException.class);
}
It's better than #Test(expected=IndexOutOfBoundsException.class) or .expect syntax because it guarantees the expected line in the test threw the exception and lets you check more details about the exception, such as message.
Maven/Gradle instructions here.
Write for each exception its own test. It will be only one thrown at a time anyway.
For example a simplified method:
void deleteCustomer( String name ) throws UnknownCustomerException
{
if ( name == null )
{
throw new NullPointerException();
}
else if ( !exists( name ) )
{
throw new UnknownCustomerException();
}
}
You have then two tests that each check if its exception is thrown:
#Test( expected = NullPointerException.class )
public void deleteCustomer_shouldThrowNullpointerIfNameIsNull() throws UnknownCustomerException
{
String name = null;
cut.deleteCustomer( name );
}
#Test( expected = UnknownCustomerException.class )
public void deleteCustomer_shouldThrowUnknownCustomerExceptionIfNameIsUnknown() throws UnknownCustomerException
{
String name = "someUnknownName";
cut.deleteCustomer( name );
}
The problem with the NullpointerException is, that the test is true/successful/green if the NPE is thrown anywhere in the method - so you should make sure, that that is not happening for the test to be meaningful.
You could add several "catch" statement into the test method for different exceptions, like:
try {
element.createCustomer(null);
Assert.fail("Exception was expected!");
} catch (NullPointerException _ignore) {
} catch (UnknownCustomerException _ignore) {
}
or with Java 87
try {
element.createCustomer(null);
Assert.fail("Exception was expected!");
} catch (NullPointerException | UnknownCustomerException _ignore) {
}
But if you switch from JUnit to TestNG, then your test will be much cleaner:
#org.testng.annotations.Test(expectedExceptions = { NullPointerException.class, UnknownCustomerException.class })
public void createCustomer() throws NullPointerException, UnknownCustomerException {
element.createCustomer(null);
}
More information about "expectedException" is here: http://testng.org/doc/documentation-main.html and example of the usage can be found here: http://www.mkyong.com/unittest/testng-tutorial-2-expected-exception-test/
I suggest that you take a closer look at the JavaDoc of ExpectedException and implement different tests for different validations, e.g.
public class CustomerTest {
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void throwsNullPointerExceptionForNullArg() {
exception.expect(NullPointerException.class);
element.createCustomer(null);
}
#Test
public void throwsUnknwonCustomerExceptionForUnkownCustomer() {
exception.expect(UnknownCustomerException.class);
// exception.expectMessage("Some exception message"); uncomment to verify exception message
element.createCustomer("unknownCustomerName");
}
#Test
public void doesNotThrowExceptionForKnownCustomer() {
element.createCustomer("a known customer");
// this test pass since ExpectedException.none() defaults to no exception
}
}

JUnit tests: How to check for errors with a try-catch block

So, I need to write a test for some (legacy) code I'm improving. In a method, I try to parse some string (which should be legal JSON). Then a possible JSONException is caught if the string doesn't represents valid JSON. Something like:
public void transformToJSON(String source) {
try {
JSONObject js = new JSONObject(new JSONTokener(item.getHtml()));
}
catch (JSONException e) {
log(e)
}
//than js is added to an Hashset and the method is done
}
So I want to write a test for good input (to see if I have generated a correct JSON-object). This is 'easy' by checking the object in the Set.
For wrong input however, I need to find out if the correct error has been thrown.
I know if an error was thrown in the code, I can check for it in the test.
By setting the rule public ExpectedException thrown=
ExpectedException.none(); and checking for it in test method.
By adding #Test(expected = JSONException.class) above the test
But both wont work for try..catch blocks.
How can I test if the proper exception is caught by catch block? I want to change as little of the source code as possible.
In the JUnit test class you can do is use fail("this should not have happened") in the try or catch block depending on what should and should not work (as in: try and catch in the JUnit class, not in your actual method!).
However, with a try/catch block within your method you cannot see whether an Exception occured or not, because it is handled within the method. So you would have to throw the exception in the method instead of catching it, i.e.,
public void transformToJSON(String source) throws JSONException { ... }
Then it will work to check whether an exception occured or not.
Alternatively you could return a boolean that states whether the transformation was successful or not. Then you can test whether the return value was true/false and if that was what you expected.
public boolean transformToJSON(String source) {
boolean success = true;
try {
JSONObject js = new JSONObject(new JSONTokener(item.getHtml()));
}
catch (JSONException e) {
log(e)
success = false;
}
//than js is added to an Hashset and the method is done
return success;
}
In your test class:
#Test
public void testTransformToJSON() {
assertTrue(transformToJSON("whatever"));
}
Based on the logging being used in the code, you can use Mockito to verify the message logged inside catch block.
Please go through the following link for more details on setting up the unit tests
http://bloodredsun.com/2010/12/09/checking-logging-in-unit-tests/
Your legacy code is swallowing the Exception. If it throws an exception, then your junit #Test ( expected = JSONException.class) would work.
I'd change the code slightly so it is
public void transformToJSON(String source) {
try {
JSONObject js = getJSON(item.getHtml()));
}
catch (JSONException e) {
log(e)
}
//than js is added to an Hashset and the method is done
}
public JSONObject getJSON(String source) throws JSONException {
return new JSONObject(new JSONTokener(source));
}
and then test against getJSON. This throws an exception and as other have said (and you) you can use the expectedException in the test class
use a bad formatted json string, and then do assertions or whatever in the catch block of ur test.
#Test
public void shouldCatchException(){
String source = "{ \"name\":\"John\", \"age\":30, \"car\":null ";
try {
jsonHelper.transformToJSON(source);
}catch (JSONException e){
Assert.assertThat(e, notNullValue());
assertTrue(StringUtils.isNotBlank(e.getMessage());
//whatever else u need to assert
}
}

Test code with Exceptions and with no exceptions at same time (JAVA)

I am writing a test for already built java class function. I am writing tests using Testng and Mockito and have a Data Provider.
This is my Test
#Test(dataProvider = "myProvider", dataProviderClass = StaticDataProvider.class,
expectedExceptions = SomeException.class)
public void myControllerTest(String argument) throws Exception {
// Mocked object bussiness\
Boolean resultantObject = business.getList(argument);
Assert.assertTrue(resultantObject);
}
This is my Controller which I want to test
public Boolean controller(String argument) {
if(argument != null) {
throw new someException();
} else {
System.out.println("Sucess");
return true;
}
}
This is my Data Providor
#DataProvider(name = "myProvider")
public static Object[][] getDirectoryList() throws Exception {
Object[][] result = null;
// case1 throws SomeException
String testData1 = null;
// case2 don't throw exception
String testData2 = "String";
result = new Object[][] { { testData1 }, { testData2 } };
return result;
}
The problem here I am facing is, I don't want to create another test just to test both buggy and non buggy code and complete my test coverage using a single test case. But when I put Expected Exception on top, it fails on correct code, and when I dont, it fails on buggy code.
NOTE: This is example code and may not work, this is just to take an idea of scenario I am working on and what I am expecting.
Even if you ignore the "one test, one assertion" purist perspective, I think most people agree you should split tests that involve error conditions from tests that prove normal behaviour.
If you want to test multiple error conditions within one test (or if you're really keen on continuing with your plan), you can use this pattern:
try {
// something that should cause an exception
fail("Exception expected");
} catch (ExactlyTheRightException e) {
// ignored
}

Categories

Resources