I need JUnit to pass only if 6 IllegalArgumentExceptions are thrown - java

Each statement new M#().multiply(-1) throws an IllegalArgumentException. Right now This passes if at least 1 exception is thrown. I need this to only pass if every single statement new M#().multiply(-1) throws an exception.
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void test(){
exception.expect(IllegalArgumentException.class);
exception.expectMessage("Integers must be positive");
new M1().multiply(-1);
new M2().multiply(-1);
new M3().multiply(-1);
new M4().multiply(-1);
new M5().multiply(-1);
new M6().multiply(-1);
}
I've been working on this for way too long now, please help.

First, I don't think a unit test should do this. You can simply create 6 tests, each creating a different class object and expecting an exception.
Yet still, for this situation, you can catch the IllegalArgumentExceptions and count how many times they occur:
int exceptionCount = 0;
try {
new M1().multiply(-1);
} catch(IllegalArgumentException ex) {
exceptionCount++;
}
try {
new M2().multiply(-1);
} catch(IllegalArgumentException ex) {
exceptionCount++;
}
...
Assert.assertEquals(exceptionCount, 6);

Related

I want to test whether the try catch block in my method is working or not

The below method is a method in my logic class that removes the required index from the list. I made an exception class so it handles an empty list or a list that will not have this index
public class LogicClass{
public void removeThisObject (ArrayList<ThisObject> thisObjList, int index){
try{
if(thisObjList.size() < (index+1)) throw new MyException ("this list is empty or does not have this index");
thisObjList.remove(index);
}catch(MyException me){
me.getMessage();
}
}
}
Now Im trying to test this method in my JUnit tests class and I would like to INTENTIONALLY trigger the exception just to see whether the exception is not working or not
public class Testing extends TestCase {
public void testRemoveObj() {
System.out.println("Checking if obj is being removed");
LogicClass logicClass = new LogicClass();
//ThisObject thisObj = new ThisObject();
//INTENTIONALLY GIVING AN EMPTY LIST FOR THE METHOD TO PROCESS
ArrayList<ThisObj> emptyList = new ArrayList<ThisObj>();
try{
//INTENTIONALLY GIVING INDEX 3 FOR AN EMPTY LIST
logicClass.removeThisObject(3,emptyList);
fail("Exception was not caught");
}catch (Exception e){
System.out.println("Exception caught successfully");
System.out.println(e.getMessage());
}
System.out.println("Removal was processed successfully. End of Test\n");
}
}
But instead the method just .... works. The exception works fine as when i comment it out in the logic the JUnit throws an IndexOutOfBoundException, when uncommented it just gives me the output:
Checking if ingredient is being removed
Removal was processed successfully. End of Test
I apologize if i missed any brackets here and there. I really hope the code was typed out correctly to follow. Im hoping that you get the jist of it.
So all in all I am trying to purposely trigger the exception in the tests so to see whether the exception was properly implemented or not. Would appreciate any help.
Thank you !!!
about your line :
So all in all I am trying to purposely trigger the exception in the tests so to see whether the exception was properly implemented or not. Would appreciate any help.
you can trigger the catch by this code :
if(true){
Exception exception = new Exception();
throw exception;
}
for your function it will be like :
public class Testing extends TestCase {
public void testRemoveObj() {
System.out.println("Checking if obj is being removed");
LogicClass logicClass = new LogicClass();
//ThisObject thisObj = new ThisObject();
//INTENTIONALLY GIVING AN EMPTY LIST FOR THE METHOD TO PROCESS
ArrayList<ThisObj> emptyList = new ArrayList<ThisObj>();
try{
//INTENTIONALLY GIVING INDEX 3 FOR AN EMPTY LIST
if(true){
Exception exception = new Exception();
throw exception;
}
logicClass.removeThisObject(3,emptyList);
fail("Exception was not caught");
}catch (Exception e){
System.out.println("Exception caught successfully");
System.out.println(e.getMessage());
}
System.out.println("Removal was processed successfully. End of Test\n");
}
}
this code will trigger an exception so you will be able to test your catch methods
Using junit without assertThrows:
#Test
void test_throwExceptionWithoutAssertThrows() {
try {
// trigger exception
} catch(MyException ex) { // Catch your specified exception
...
assertStatements // optional
return; // Stop execution at this point.
}
fail(); // we didn't catch, assert and return. Something went wrong.
}
Using junit5 you can assert Exceptions with the assertThrows(< TargetedException >.class, lambdaExpression) like this:
#Test
void whenRemoveThisObjectCalled_thenMyExceptionThrown() {
LogicClass logicClass = new LogicClass();
assertThrows(MyException.class, () -> {
List<Integer> emptyList = Collections.emptyList();
logicClass.removeThisObject(1, emptyList);
});
}
Explanation:
After your try-catch block executed, Exception or not, the program will continue. That is why you will see your "was successful" output, even if your desired Exception was thrown. If you know which scenario of exception throwing you want to test, it's not a good idea to "test try-catch in general", because we can assume that try-catch will work. Instead you can test, if your Exception is thrown under specified circumstances (see code above).
try this answer will post the success when it done :
public class Testing extends TestCase {
public void testRemoveObj() {
System.out.println("Checking if obj is being removed");
LogicClass logicClass = new LogicClass();
//ThisObject thisObj = new ThisObject();
//INTENTIONALLY GIVING AN EMPTY LIST FOR THE METHOD TO PROCESS
ArrayList<ThisObj> emptyList = new ArrayList<ThisObj>();
try{
//INTENTIONALLY GIVING INDEX 3 FOR AN EMPTY LIST
if(true){
Exception exception = new Exception();
throw exception;
}
logicClass.removeThisObject(3,emptyList);
fail("Exception was not caught");
System.out.println("Removal was processed successfully. End of Test\n");
}catch (Exception e){
System.out.println("Exception caught successfully");
System.out.println(e.getMessage());
}
}
}

JUnit right way of test expected exceptions

Hello guys I was wondering if this way of testing my exception is ok, i have this exception i need to throw in the second test annotation, im receiving as result a red evil bar, and a succeed and a failure, as you can guess the failure is my concern, i have a fail(); there but the reason is because i read thats the way to test the exception and now im confused.
Also i have to say im willin get the green bar because im expecting the exception, but i dont know if failure is the right way to see the answer of the expected exception.
Also if you had any advice, I would appreciate it
#Before
public void setUp() throws Exception {
LogPack.logPacConfig(Constants.LOGGING_FILE);
gtfri = "+RESP:GTFRI,380502,869606020101881,INCOFER-gv65,,10,1,1,0.0,0,888.1,-84.194560,9.955602,20170220074514,,,,,,0.0,,,,100,210100,,,,20170220074517,40A2$";
weirdProtocol = "+RESP:GRI,380502,869606020101881,INCOFER-gv65,,10,1,1,0.0,0,888.1,-84.194560,9.955602,20170220074514,,,,,,0.0,,,,100,210100,,,,20170220074517,40A2$";
factory = new LocomotiveFactory();
}
#Test
public void GTFRICreationTester_shouldPass() throws TramaConProtolocoloDesconocido {
assertTrue(factory.createLocomotive(gtfri, false, new Date()) instanceof LocomotiveGTFRI);
}
#Test(expected = TramaConProtolocoloDesconocido.class)
public void GTFRICreationTester_shouldFail() {
try {
factory.createLocomotive(weirdProtocol, false, new Date());
fail("Expected an TramaConProtolocoloDesconocido");
} catch (TramaConProtolocoloDesconocido e) {
//assertSame("exception thrown as expected", "no se conoce el protocolo dado para la creacion de este factory", e.getMessage());;
}
}
There is 3 most common ways to test expected exception:
First one is the most common way, but you can test only the type of expected exception with it. This test will fail if ExceptionType won't be thrown:
#Test(expected = ExceptionType.class)
public void testSomething(){
sut.doSomething();
}
Also you cannot specify the failure message using this approach
The better option is to use ExpectedException JUnit #Rule. Here you can assert much more for expected exception
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void testSomething(){
thrown.expect(ExceptionType.class);
thrown.expectMessage("Error message");
thrown.expectCause(is(new CauseOfExeption()));
thrown.reportMissingExceptionWithMessage("Exception expected");
//any other expectations
sut.doSomething();
}
The third option will allow you to do the same as with using ExpectedException #Rule, but all the assertion should be written manually. However the advantage of this method is that you can use any custom assertion and any assertion library that you want:
#Test
public void testSomething(){
try{
sut.doSomething();
fail("Expected exception");
} catch(ExceptionType e) {
//assert ExceptionType e
}
}
You can use ExpectedException which can provide you more precise information about the exception expected to be thrown with the ability to verify error message, as follows:
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
public class TestClass {
#Rule
public ExpectedException expectedException = ExpectedException.none();
#Test
public void GTFRICreationTester_shouldFail() {
expectedException.expect(TramaConProtolocoloDesconocido.class);
factory.createLocomotive(weirdProtocol, false, new Date());
}
}
To expolore more about it, you can refer to the blog written by me here - Expected Exception Rule and Mocking Static Methods – JUnit
if your are using java 8, I would recommend to go for the AssertJ library
public void GTFRICreationTester_shouldFail() {
assertThatExceptionOfType(EXCEPTION_CLASS).isThrownBy(() -> { factory.createLocomotive(weirdProtocol, false, new Date()) })
.withMessage("MESSAGE")
.withMessageContaining("MESSAGE_CONTAINING")
.withNoCause();
}
with that solution you can at one verify exception type, with message etc.
for more reading, take a look at:
http://joel-costigliola.github.io/assertj/assertj-core-features-highlight.html#exception-assertion
You don't need to catch the Exception with try-catch
#Test(expected = TramaConProtolocoloDesconocido.class)
public void GTFRICreationTester_shouldFail() {
factory.createLocomotive(weirdProtocol, false, new Date());
}
If we suppose that factory.createLocomotive(weirdProtocol, false, new Date()) throws the exception when you apply a scenario that makes the exception thrown.
void createLocomotive(param...) {
//something...
throw new TramaConProtolocoloDesconocido();
}

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
}

Android File manipulation tests with JUNIT

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.

Checking for 2 expected values in Junit

I have a java program which throws an exception with 2 different messages for 2 different scenarios and I want the Junit test case to check for equality for both of these messages. As an example -
public void amethod() {
// do some processing
if(scenario1 == true) {
throw new MySystemException("An error occured due to case 1 being incorrect.");
}
else if(scenario2 == true) {
throw new MySystemException("An error occured as case 2 could not be found");
}
}
Now the JUnit for this would be something like-
public void testAMethod() {
// do something
assertEquals("Expected", "Actual");
}
As I understand, in this above example, if I use the Scenario1 exception message the junit will fail when an exception is thrown for Scenario2 and vice versa.
I would like to know if there is any other way provided in Junit by which I can use this one test method and check for both the messages for the test to pass?
Something like an OR, if possible to provide the "Expected" value with both these expected message.
I hope my query is clear enough.
Thanks
UPDATE
Sorry for the delayed response, had got caught up with some other urgent matter.
Thank you all for the very nice suggestions, it certainly has helped me to understand a bit better now.
Eventually, to keep it rather simple I decided to implement a somewhat similar solution suggested by Don Roby. So created a new test class which looks like -
public void testAMethodScenario1() {
// do the necessary
assertEquals("Expected Exception Message 1", "Actual");
}
public void testAMethodScenario2() {
// do the necessary
assertEquals("Expected Exception Message 2", "Actual");
}
Thank you all again for your responses.
I think you need to manually catch the exception (for each scenario) and individually check the message:
try {
// trigger scenario 1
fail("An exception should have been thrown here !");
} catch (MySystemException e1) {
assertEquals("Wrong error message", m1, e1.getMessage());
}
try {
// trigger scenario 2
fail("An exception should have been thrown here !");
} catch (MySystemException e2) {
assertEquals("Wrong error message", m2, e2.getMessage());
}
Of course, you can have these scenarios defined as enum constants and simply iterate through them and check each of them within a loop, since the "copy/paste design pattern" is pretty obvious in the above code. :)
You seem to be asking two things here, how to test an exception and how to assert that a value matches either of two possible expected values.
To test for an exception, you can either use a JUnit4 annotation:
#Test(expected=MySystemException.class)
public void testException() {
amethod();
}
or use a try-catch in your test:
#Test
public void testException() {
try {
amethod();
fail("MySystemException expected");
}
catch (MySystemException e) {
// Success!
}
}
And if you have only one message, in the try-catch version you can assert that you got it with an AssertEquals in the catch block.
The best testing would have separate tests for your two scenarios, and expect the correct single message. Better code might in fact have distinct exceptions for the two situations.
But the need for a more complex assertion than simple equality does come up anyway, and there's an elegant solution for it in Hamcrest matchers.
Using that for this situation, you could write something like (untested - don't trust my syntax completely):
#Test
public void testException() {
try {
amethod();
fail("MySystemException expected");
}
catch (MySystemException e) {
String expectedMessage1 = "An error occured due to case 1 being incorrect.";
String expectedMessage2 = "An error occured as case 2 could not be found";
assertThat(e.getMessage(),
anyOf(equalTo(expectedMessage1), equalTo(expectedMessage2)));
}
}
Can you predict which scenario will occur? If so, Costi's answer is correct. If not, because there's some randomness or whatever, you can write:
#Test
public void testAmethodThrowsException() {
try {
amethod();
fail("amethod() should have thrown an exception");
}
catch (MySystemException e) {
String msg = e.getMessage();
assertTrue("bad message: " + msg, msg.equals("An error occured due to case 1 being incorrect.") || msg.equals("An error occured as case 2 could not be found"));
}
}
The declared types of exception thrown bya method are part of its API. If you really want to distinguish different failure modes, you should declare a different exception type for each failure mode.
So, something like this:
/**
* Do something.
* #throws MySystemException1 in case 1.
* #throws MySystemException2 if Foo not found.
*/
public void amethod() {
// do some processing
if(scenario1 == true) {
throw new MySystemException1("Case 1.");
}
else if(scenario2 == true) {
throw new MySystemException2("Foo not found");
}
}
#Rule solution in JUnit4:
public class ExceptionRule implements MethodRule {
#Override
public Statement apply(final Statement base, final FrameworkMethod method, Object target) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
base.evaluate();
Assert.fail();
} catch (MySystemException e) {
if(scenario1)
assertEquals("Expected error message1", e1.getMessage();
if(scenario2)
assertEquals("Expected error message2",e1.getMessage();
}
}
};
}
}
In your testcase, use the Rule:
#Rule public ExceptionRule rule = new ExceptionRule();
JUnit 4 provides (Expected Exception.class)
#Test(expected= MySystemException.class) public void empty() {
// what ever you want
}
Google: Expected Exceptions JUnit for more info.
BDD Style Solution with Catch Exception
#Test
public void testAMethodScenario1() {
//given scenario 1
when(foo).amethod();
then(caughtException())
.isInstanceOf(MySystemException.class)
.hasMessage("An error occured due to case 1 being incorrect.");
}
#Test
public void testAMethodScenario2() {
//given scenario 2
when(foo).amethod();
then(caughtException())
.isInstanceOf(MySystemException.class)
.hasMessage("An error occured as case 2 could not be found");
}
Source code
https://gist.github.com/mariuszs/7490875
Dependencies
com.googlecode.catch-exception:catch-exception:1.2.0
A better solution with #Rule, you can assert both exception and expection message as well.
#Rule
public ExpectedException expectedException = ExpectedException.none();
#Test
public void aMethod_Scenario1True_ThrowsException() {
expectedException.expect(MySystemException.class);
expectedExcepion.expectMessage("An error occured due to case 1 being incorrect.");
//when().thenReturn();
//handle the repositories, static methods and other sub methods, if needed
amethod();
}
#Rule is the more elegant way to write the exception.

Categories

Resources