This question already has answers here:
throw checked Exceptions from mocks with Mockito
(5 answers)
Closed 5 years ago.
I have the below class
There is an answer to this in StackOverflow but it deals with List throw checked Exceptions from mocks with Mockito. I like to look into this condition. Not getting where I am missing.
public SimpleClass{
private SimpleClass() {}
public void runMethod(request,String,Map,Object,Object) {
try {
doesSomething()....
}
}
catch(Exception e) {
String message = "" + request.getAttribute(X) + "Some message";
Logger.Log(param1 + param2 + message);
}
}
My Test method looks like below. I trying to run the coverage with the JUnit but the Catch Block is not covered, so Wrote the below test method. It throws the below exception. Not able to get where I am missing.
public class SimpleClassTest{
#Test
public void testCatchBlock() {
SimpleClass instanceObj = PowerMockito.mock(SimpleClass.class);
Mockito.doThrow(new Exception())
.when(instanceObj)
.runMethod(request, anyString(), anyMap(), anyObject(), anyObject());
}
}
Exception Thrown
org.mockito.exceptions.base.MockitoException:
Checked exception is invalid for this method!
Invalid: java.lang.Exception
Edit
I am able to run the method by giving NullPointerException. When I try for code coverage with Junit, the catch block is completely shown as red, and the catch phrase is shown yellow. How do I achieve 100% coverage and how to test the String message in the catch block.
You are getting unit testing with mocking wrong. Here:
SimpleClass instanceObj =PowerMockito.mock(SimpleClass.class);
There is no point in mocking the class that is under test!
When you mock that class, you get a stub that has "nothing to do" with your real implementation. A "working setup" would look more like:
public void methodUnderTest(X x, ...) {
try {
x.foo();
} catch (Exception e) {
...
}
and
X mockedX = mock(X.class);
when(x.foo()).thenThrow(new WhateverException());
underTest.methodUnderTest(mockedX); ...
and then you could try to verify for example that the logger saw that expected logging call. In other words: you either use a mock to allow your code under test to do its job (with you being in control!) or to verify that some expected call took place on a mock object.
But as said: it doesn't make any sense to mock that class that you want to test. Because a mocked object doesn't know anything about the "real" implementation!
Manipulate the environment so that doesSomething() throws the Exception you want. Since we do not know what doesSomething() really does, one cannot say more.
Related
In TestNG, when we want to test a scenario in which an exception should be thrown one can write something like the following
#Test(expected=IndexOutOfBoundsException.class, expectedExceptionsMessageRegExp="*")
public void sampleExpectedExceptionTest() {
List emptyList = new ArrayList();
// Following line should throw an IndexOutOfBoundsException
emptyList.get(0);
}
I have seen that some people write the tests in following style.
#Test
public void sampleExpectedExceptionTest() {
// several lines here..
List emptyList = new ArrayList();
try {
emptyList.get(0);
Assert.assertFail("Expected IndexOutOfBoundsException but wasn't thrown");
} catch (IndexOutOfBoundsException e) {
// ignore
}
// ... more lines of code asserting exceptions similar to above try catch scenario
}
I dislike the above style primarily because it is very verbose and also because people using it usually write multiple tests in one test case. However, the argument given in it's favour is that it allows users to pinpoint the assertion to a particular line and hence it is better.
Recently I learnt about JUnit's #Rule annotation
public class SampleExceptionTest {
#Rule
public final ExpectedException exception = ExpectedException.none();
#Test
public void sampleExpectedExceptionTest() {
List emptyList = new ArrayList();
exception.expect(IndexOutOfBoundsException.class);
emptyList.get(0);
}
}
This not only allows users to pinpoint the assertion to a line but it also discourages users to write multiple tests in one test case as once an exception is thrown the code exits and you can not test for multiple assertions. I want to know is there a similar option (or an idiom) in TestNG? I know that I can use expected
I suggest you have a look at the Catch-Exception library. It allows you to perform multiple assertions on the exception and any other relevant assertions. You can use it with JUnit and TestNG and any assertion framework you want.
Sample:
#Test
public void catchExceptionTest() {
// given: an empty list
List<Object> myList = new ArrayList<>();
// when: we try to get the first element of the list
// then: catch the exception if any is thrown
catchException(myList).get(1);
// then: we expect an IndexOutOfBoundsException
Exception e = caughtException();
// Use JUnit, TestNG, AssertJ etc. assertions on the "e" exception
assert e instanceof IndexOutOfBoundsException;
}
You'll find more examples on the project page.
I have a void method and I want to test it. How do I do that?
Here's the method:
public void updateCustomerTagCount() {
List<String> fileList = ImportTagJob.fetchData();
try {
for (String tag : fileList) {
Long tagNo = Long.parseLong(tag);
Customer customer = DatabaseInterface.getCustomer(tagNo);
customer.incrementNoOfTimesRecycled();
DatabaseInterface.UpdateCustomer(customer);
}
} catch(IllegalArgumentException ex) {
ex.printStackTrace();
}
}
when the method returns void, you can't test the method output. Instead, you must test what are the expected consequences of that method. For example:
public class Echo {
String x;
public static void main(String[] args){
testVoidMethod();
}
private static void testVoidMethod() {
Echo e = new Echo();
//x == null
e.voidMethod("xyz");
System.out.println("xyz".equals(e.x)); //true expected
}
private void voidMethod(String s) {
x = s;
}
}
It might not be always true, but basic concept of unit test is to check if function works as expected and properly handling errors when unexpected parameters/situation is given.
So basically unit test is against the functions that takes input parameters and return some output so we can write those unit test.
The code like yours, however, includes some other dependency (database call) and that's something you can't execute unless you write integration-test code or real database connection related one and actually that's not recommended for unit test.
So what you need to do might be introducing unit test framework, especially Mockto/Powermock or some other stuff that provides object mocking feature. With those test framework, you can simulate database operation or other function call that is going to be happening outside of your test unit code.
Also, about how do I test void function, there is nothing you can with Assert feature to compare output since it returns nothing as you mentioned.
But still, there is a way for unit test.
Just call updateCustomerTagCount() to make sure function works. Even with just calling the function, those unit test can raise your unit test coverage.
Of course for your case, you need to mock
ImportTagJob.fetchData();
and
DatabaseInterface.getCustomer(tagNo);
and have to.
Let mocked
ImportTagJob.fetchData();
throw empty list as well as non-empty list and check if your code works as you expected. Add exception handling if necessary. In your code, there are two condition depends on whether fieList are null or non-null, you need to test it.
Also, mock those objects and let them throw IllegalArgumentException where you expect it to be thrown, and write an unit test if the function throws a exception. In Junit, it should be like
#Test(expected = IllegalArgumentException.class)
public void updateCustomerTagCountTest(){
// mock the objects
xxxxx.updateCustomerTagCount();
}
That way, you can ensure that function will throw exception properly when it has to.
This is my code which I want to force to throw a Remote Exception:
transient Bicycle b=null;
public Bicycle getBicycle() {
if(b==null) {
try {
b=new Bicycle(this);
} catch (RemoteException ex) {
Logger.getLogger(Bicycle()).log(Level.SEVERE, null, ex);
}
}
return b;
}
Here is the JUnit test I am running with Mockito:
boolean exceptionThrown=false;
Bicycle mockB = mock(Bicycle);
mockB.setBicycle(null);
stub(mockB.getBicycle()).toThrow(new RemoteException(){boolean exceptionThrown = true;});
assertTrue(exceptionThrown);
I keep receiving the following error:
Checked exception is invalid for this method!
Any help will be appreciated.
Edit:
Instead of
stub(mockB.getBicycle()).toThrow(new RemoteException(){boolean exceptionThrown = true;});
I have also tried
doThrow(new RemoteException(){boolean exceptionThrown = true;}).when(mockB).getBicycle();
and
Mockito.when(mockB.getBicycle()).thenThrow(new RemoteException(){boolean exceptionThrown=true;});
Still no luck.
Edit2 - gone one step further after fully understanding the API and using it correctly:
when(mockB.getBicycle()).thenThrow(new RuntimeException());
I don't know how to make the assert now. I tried putting a boolean once the exception gets called but the assert cannot see the boolean.
Any ideas?
The getBicycle() method will never return a RuntimeException. The code itself is catching the RuntimeException and, when caught, writes to the logger. The method itself will either return the Bicycle or null.
You will need to rethink how you want the getBicycle method operates. It could re-throw the RuntimeException atfer logging if you want the RuntimeException to bubble through. But, based on how that's written, the RuntmeException will never make it out to the JUnit test
I use Assert class to check if some text is on the page, this command stop test executing if text is not present. I want use verification. Could someone tell where I could find documentation on such methods?
I mean WebDriver, junit. For example such code
String text=("Terms");
List<WebElement> list = driver.findElements(By.xpath("//*[contains(text(),'" + text + "')]"));
Assert.assertEquals("Text not found!", "Terms", list);
If there isn't text "Term" on page junit test will interrupt test, but I need just take error message and continue test.
If you want to continue execution of your test cases even if some some result you are expecting fails and get to see the results at the end of complete execution.
You can do something like this -
Declare a variable to store all the test case results which fail during execution and then in the tearDown method you can call Assert.fail(String message)
StringBuffer errors = new StringBuffer();
#Test
public void testSomething(){
if(!"data".equals(text)){
addErrors(text +"not equal to data");
}
// add any number of if statements to check anything else
}
#After()
public void tearDown(){
if(errors.length()!=0){
Assert.fail(errors.toString());
}
}
public String addErrors(String message){
errors = errors.append(message+"\n");
}
Now in the testSomething() method you can check or test any number of WebElements on the webpage and all you have to do is have a simple if statement to check if some thing is correct and if not then call the addErrors() method. Hope this helps you.
Sounds like you just need to catch and handle AssertionError thrown by the various methods of Assert (documented here). Something like this:
try {
Assert.assertEquals("Text not found!", "Terms", list);
} catch (AssertionError e) {
System.err.println("Assertion failed: " + e.getMessage());
}
Is it possible to test for multiple exceptions in a single JUnit unit test? I know for a single exception one can use, for example
#Test(expected=IllegalStateException.class)
Now, if I want to test for another exception (say, NullPointerException), can this be done in the same annotation, a different annotation or do I need to write another unit test completely?
You really want the test to do one thing, and to test for that. If you're not sure as to which exception is going to be thrown, that doesn't sound like a good test to me.
e.g. (in pseudo-code)
try {
badOperation();
/// looks like we succeeded. Not good! Fail the test
fail();
}
catch (ExpectedException e) {
// that's fine
}
catch (UnexpectedException e) {
// that's NOT fine. Fail the test
}
so if you want to test that your method throws 2 different exceptions (for 2 sets of inputs), then you'll need 2 tests.
This is not possible with the annotation.
With JUnit 4.7 you can use the new ExpectedException rule
public static class HasExpectedException {
#Interceptor
public ExpectedException thrown= new ExpectedException();
#Test
public void throwsNothing() {
}
#Test
public void throwsNullPointerException() {
thrown.expect(NullPointerException.class);
throw new NullPointerException();
}
#Test
public void throwsNullPointerExceptionWithMessage() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("happened?");
throw new NullPointerException("What happened?");
}
}
More see
JUnit 4.7: Interceptors: expected exceptions
Rules in JUnit 4.7
If updating to JUnit 4.7 is not possible for you, you have to write a bare unit test of the form
public test() {
try {
methodCall(); // should throw Exception
fail();
}
catch (Exception ex) {
assert((ex instanceof A) || (ex instanceof B) || ...etc...);
...
}
}
Although this is not possible with JUnit 4, it is possible if you switch to TestNG, which allows you to write
#Test(expectedExceptions = {IllegalArgumentException.class, NullPointerException.class})
Use catch-exception:
// test
public void testDo() {
// obj.do(1) must throw either A or B
catchException(obj).do(1);
assert caughtException() instanceof A
|| caughtException() instanceof B;
// obj.do(2) must throw A but not SubclassOfA
catchException(obj).do(2);
assert caughtException() instanceof A
&& !(caughtException() instanceof SubclassOfA);
}
#Test(expected=Exception.class)
This will throw all possible exceptions.
How would you expect to "expected"s to work? A method can only throw one exception.
You would have to write a different unit test for each way the method can fail. So if the method legitimately throw two exceptions then you need two tests set up to force the method of throwing each exception.
Keep the tests as simple and short as possible. The intention of a JUnit-Test is to test only one simple functionality or one single way of failure.
Indeed, to be safe, you should create at least one test for every possible execution way.
Normally, this is not always possible because if you have a method that analyses a string, there are so many possible string combinations that you cannot cover everything.
Keep it short and simple.
You can have 30-40 testing methods for one single method easily... does it really matter?
Regards