问题
I have to write JUnit test cases for existing code where I do not have the liberty / opportunity to re-write the actual code. In many of these classes, the methods catch an exception internally and just log it. And the exceptions are not based on any parameters which could be manipulated to attempt to throw the exception, but are thrown by the code inside the method - e.g. - the method may open a file and catch IOException and just log it. Basically, many of the methods just eat all the possible exceptions - which I know is very bad practice, but at this point in time, we have to continue with it.
Is it possible to have code coverage for such situations. Since the classes have a lot of such constructs, it keeps the code coverage of the class very low and I have to get the coverage to at least 75%
I have tried different things found from different examples but none of them have worked.
UPDATE
Adding an example of the code for which I need to add JUnit tests.
public StringBuilder getTxtFiles(InputStream in) {
StringBuilder out = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
try {
while ((line = reader.readLine()) != null) {
out.append(line);
}
} catch (IOException e) {
System.out.println("Error Occurred ");
e.printStackTrace();
}
return out;
}
This is just an example. There are different kinds of object creations with "new" and different exceptions thrown. What I need is an example of writing a JUnit test that will provide coverage for catch clauses of this type.
Update 2 - Another Example
Class to be tested
package com.test.model;
import com.datastax.driver.core.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.annotation.Transient;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;
import javax.persistence.Entity;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
@Entity
@Table("test_master")
public class TestMaster implements Serializable {
private static final Logger LOGGER = LoggerFactory.getLogger(TestMaster.class);
private static final long serialVersionUID = 1L;
@PrimaryKeyColumn(name = "test_number", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private String testNumber;
@Column(value = "test_requested_date")
private LocalDate testRequestedDate;
@Column(value = "transfer_date")
private LocalDate transferDate;
public LocalDate getTestRequestedDate() {
return testRequestedDate;
}
public void setTestRequestedDate(LocalDate testRequestedDate) {
this.testRequestedDate = testRequestedDate;
}
public void setOtherAppTestRequestedDate(String otherAppTestRequestedDate) {
this.otherAppTestRequestedDate = otherAppTestRequestedDate;
}
public void setOtherAppTestTransferdate(String otherAppTestTransferdate) {
this.otherAppTestTransferdate = otherAppTestTransferdate;
}
@Transient
private String otherAppTestRequestedDate;
@Transient
private String otherAppTestTransferdate;
public static Date subtractDays(Date date, int days) {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);
cal.add(Calendar.DATE, -days);
return cal.getTime();
}
public String getTestNumber() {
return testNumber;
}
public void setTestNumber(String loanNumber) {
this.testNumber = testNumber;
}
public String getOtherAppTestRequestedDate() {
String ourformat ="";
LOGGER.info("getTestRequestedDate()--->"+getTestRequestedDate());
try {
if (getTestRequestedDate() != null && getTestRequestedDate().getMillisSinceEpoch() > 0) {
Date d = new Date(getTestRequestedDate().getMillisSinceEpoch());
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
ourformat = formatter.format(d.getTime());
System.out.println("getOtherAppTestRequestedDate()--->" + ourformat);
}
}catch(Exception e){
e.printStackTrace();
}
return ourformat;
}
public LocalDate getTransferDate() {
return transferDate;
}
public void setTransferDate(LocalDate transferDate) {
this.transferDate = transferDate;
}
public String getOtherAppTestTransferdate(){
String ourformat = "";
LOGGER.info("TranferDate"+getTransferDate());
SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat stringFormatter = new SimpleDateFormat("yyyyMMdd");
try {
if (getTransferDate() != null && getTransferDate().getMillisSinceEpoch() > 0) {
ourformat= getTransferDate().toString();
Date date1=format.parse(ourformat);
ourformat=stringFormatter.format(date1);
System.out.println("printing getIdeaTransferdate" + ourformat);
}
}catch(Exception e){
e.printStackTrace();
}
return ourformat;
}
}
Sample JUnit test Class
package com.test.model;
import com.datastax.driver.core.LocalDate;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import static org.mockito.Matchers.anyString;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@PrepareForTest({SimpleDateFormat.class})
@PowerMockIgnore("javax.management.*")
public class TestMasterTest {
@InjectMocks
TestMaster model;
@Test
public void testGetIdeaTransferdateException() throws ParseException {
SimpleDateFormat sdfMock = PowerMockito.mock(SimpleDateFormat.class);
PowerMockito.when(sdfMock.parse(anyString())).thenThrow(new ParseException("Exception cause", 1));
model.setTransferDate(LocalDate.fromYearMonthDay(2018, 1, 3));
when(model.getTransferDate()).thenReturn(null);
// Tried this with anyString() instead of null
// also tried with "when" clause above the model.setTransfer clause
Assert.assertEquals("20180103",model.getOtherAppTestTransferdate());
Assert.assertNotNull("Expected date : 20180103",model.getOtherAppTestTransferdate());
}
}
This is the error I get
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Or 'a static method call on a prepared class`
For example:
@PrepareForTest( { StaticService.class })
TestClass{
public void testMethod(){
PowerMockito.mockStatic(StaticService.class);
when(StaticService.say()).thenReturn(expected);
}
}
Also, this error might show up because:
1. inside when() you don't call method on mock but on some other object.
2. inside when() you don't call static method, but class has not been prepared.
at org.powermock.api.extension.reporter.MockingFrameworkReporterFactoryImpl$PowerMockitoReporter.missingMethodInvocation(MockingFrameworkReporterFactoryImpl.java:66)
at com.test.model.TestMasterTest.testGetIdeaTransferdateException(TestMasterTest.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:148)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:140)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.withContextClassLoader(DelegatingPowerMockRunner.java:131)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:140)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:121)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
2018-09-13 08:29:03.368-0400 INFO o.s.c.support.GenericApplicationContext Closing org.springframework.context.support.GenericApplicationContext@61c9c3fd: startup date [Thu Sep 13 08:29:00 EDT 2018]; root of context hierarchy
How can I achieve this?
Thank you
来源:https://stackoverflow.com/questions/52267168/how-to-simulate-caught-and-logged-exceptions-inside-a-method-and-create-junit-te