AEM Mockito Junit 5 unable to cover catch block - mockito

How do I cover the catch block for for the methods that return void in junit5 and mockito.
below mentioned dump method return void and throws RepositoryException and JSONException.
tidyJosnItemWrite.dump(node, stringWriter, -1);

You need to write new test case like below.
#Test
void testGetJson {
doThrow(new RepositoryException()).when(tidayJsonItemWriter).dump(Mockito.any(), Mockito.any(), Mockito.any());
ctx.addModelsForClasses(Aem.class);
ctx.getJson(node, tidyJosnItemWriter);
}

Related

mockito, how to coverage test the catch block

Android app, Having a function calling another function, that function may throw
static string SOME_DEFINE_1 = "some_define_1";
......
void myFunc() {
try {
HashMap<String, String> data = new HashMap<>();
data.put("key_1", SOME_DEFINE_1);
otherObject.func(data);
} catch (Throwable ex){
Log.e(TAG, "+++ exception from otherObject.func(), "+ ex.toString());
// do something
anotherFunc();
}
}
How to test the catch block is called when unit testing the myFunc?
It isn't clear in your example where otherObject comes from, but in general, to test the exception handling blocks you need code that will throw the exception. In this example, one way may be to mock the otherObject and then use thenThrow to cause it to throw an exception when the func(data) method is called. You could use a spy of the class you are testing and stub the anotherFunc method so you can replace it with something else and then verify if it was invoked for the conditions you expect to throw the exception.
These articles show the general approach:
https://www.baeldung.com/mockito-spy - (number 4)
https://www.baeldung.com/mockito-exceptions
So in a pseudo-code example:
// arrange
myClassUnderTest = spy(TheClassUnderTest);
otherObject = mock(OtherObject);
doNothing().when(myClassUnderTest).anotherFunc();
doThrow(new RuntimeException("simulated exception")).when(otherObject).func(any());
// act
myClassUnderTest.myFunc();
// assert
verify(myClassUnderTest , times(1)).anotherFunc();

Mockito Multipart file argument matcher

I am trying to have an integration test that throwns an exception for a void method to simulate a downed service. The method has a string param and a multipart file as a param and it does not seem to be working even though an exception is thrown for a void method with two string parameters.
Working integration test:
#Test
#DisplayName("500 response -- downed case mgmt microservice")
public void downedCaseMgmt() throws Exception {
BDDMockito.doThrow(new RuntimeException("mocking an error")).when(reportEventService).reportDocUpload(ArgumentMatchers.any(String.class), ArgumentMatchers.anyString());
//Rest assured portion
given().
multiPart("file", xlsxGoodFile).
params(paramsMap).
when().
post("").
then().
statusCode(500);
}
Non-working integration test:
#Test
#DisplayName("500 response -- downed object storage")
public void downedObjectStorage() throws Exception {
BDDMockito.doThrow(new RuntimeException("mocking an error")).when(objectStorageService).saveFileToObjectStorage(ArgumentMatchers.anyString(), ArgumentMatchers.any(File.class));
//Rest assured portion
given().
multiPart("file", xlsxGoodFile).
params(paramsMap).
when().
post("").
then().
statusCode(500);
}
Turns out that the function saveFileToObjectStorage had a null value because of the mockbean on objectStorageService and the fact that I was mocking a return. Error on my part and I resolved it with the following code:
#Test
#DisplayName("500 response -- downed db")
public void downedDb() throws Exception {
BDDMockito.doThrow(new RuntimeException("mocking an error")).when(excelDataRepository).
save(ArgumentMatchers.any());
//Rest assured portion
given().
multiPart("file", xlsxGoodFile).
params(paramsMap).
when().
post("").
then().
statusCode(500);
}
NOTE: the any() of ArgumentMatchers

Spring integration with retry with ExceptionClassifierRetryPolicy

I am using int:request-handler-advice-chain with my service activator. It is working correctly with org.springframework.retry.policy.SimpleRetryPolicy however I would like to use org.springframework.retry.policy.ExceptionClassifierRetryPolicy to allow for a different number of retries based on the exception thrown by the service activator.
The problem I am having is that by the time the exception gets to the ExceptionClassifierRetryPolicy it is a
org.springframework.integration.MessageHandlingException
Can anyone advise on the best approach for get the cause (i.e my exception) from the MessageHandlingException made available to the ExceptionClassifierRetryPolicy?
Solution thanks to Artem's suggestion below:
Create a subclass of SubclassClassifier that returns the cause in the case of MessagingException
public class MessagingCauseExtractingSubclassClassifier extends SubclassClassifier<Throwable, RetryPolicy> {
private static final Logger LOG = LoggerFactory.getLogger(MessagingCauseExtractingSubclassClassifier.class);
public MessagingCauseExtractingSubclassClassifier(final Map<Class<? extends Throwable>, RetryPolicy> policyMap, final RetryPolicy retryPolicy) {
super(policyMap, retryPolicy);
}
#Override
public RetryPolicy classify(final Throwable throwable) {
Throwable t = throwable;
if (t instanceof MessagingException) {
t = t.getCause();
LOG.debug("Throwable is instanceof MessagingException so classifying cause type: {}", t.getClass());
}
return super.classify(t);
}
}
Then a new ExceptionClassifierRetryPolicy subclass that uses the new classifier and policyMap
public class MessasgeCauseExtractingExceptionClassifierRetryPolicy extends ExceptionClassifierRetryPolicy {
#Override
public void setPolicyMap(final Map<Class<? extends Throwable>, RetryPolicy> policyMap) {
final MessagingCauseExtractingSubclassClassifier classifier = new MessagingCauseExtractingSubclassClassifier(
policyMap, new NeverRetryPolicy());
setExceptionClassifier(classifier);
}
}
Currently this won't support retying on MessagingException but this is fine for our use case. Otherwise works perfectly.
The BinaryExceptionClassifier has traverseCauses option to analize the whole StackTrace until the proper condition.
Exactly this option is with one of SimpleRetryPolicy constructor:
public SimpleRetryPolicy(int maxAttempts, Map<Class<? extends Throwable>, Boolean> retryableExceptions,
boolean traverseCauses) {
Please, take a look if that variant is feasible for you.

Java: Running transaction in multithreaded environment

We are launching a website that will have a very heavy volume for a short period of time. It is basically giving tickets. The code is written in Java, Spring & Hibernate. I want to mimic the high volume by spawning multiple threads and trying to get the ticket using JUnit test case. The problem is that in my DAO class the code just simply dies after I begin transaction. I mean there is no error trace in the log file or anything like that. Let me give some idea about the way my code is.
DAO code:
#Repository("customerTicketDAO")
public class CustomerTicketDAO extends BaseDAOImpl {// BaseDAOImpl extends HibernateDaoSupport
public void saveCustomerTicketUsingJDBC(String customerId) {
try{
getSession().getTransaction().begin(); //NOTHING HAPPENS AFTER THIS LINE OF CODE
// A select query
Query query1 = getSession().createSQLQuery("my query omitted on purpose");
.
.
// An update query
Query query2 = getSession().createSQLQuery("my query omitted on purpose");
getSession().getTransaction().commite();
} catch (Exception e) {
}
}
Runnable code:
public class InsertCustomerTicketRunnable implements Runnable {
#Autowired
private CustomerTicketDAO customerTicketDAO;
public InsertCustomerTicketRunnable(String customerId) {
this.customerId = customerId;
}
#Override
public void run() {
if (customerTicketDAO != null) {
customerTicketDAO.saveCustomerTicketUsingJDBC(customerId);
}
}
}
JUnit method:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"file:src/test/resources/applicationContext-test.xml"})
public class DatabaseTest {
#Before
public void init() {
sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
customerTicketDAO = (CustomerTicketDAO)applicationContext.getBean("customerTicketDAO");
}
#After
public void end() throws Exception {
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSession(session);
}
#Test
public void saveCustomerTicketInMultipleThreads () throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
for (int i=0; i<1000; i++) {
executor.submit(new InsertCustomerTicketRunnable(i));
}
// This will make the executor accept no new threads
// and finish all existing threads in the queue
executor.shutdown();
// Wait until all threads are finish
executor.awaitTermination(1, TimeUnit.SECONDS);
}
I see no data being inserted into the database. Can someone please point me as to where I am going wrong?
Thanks
Raj
SessionFactory is thread safe but Session is not. So my guess is that you need to call SessionFactoryUtils.getSession() from within each thread, so that each thread gets its own instance. You are currently calling it from the main thread, so all children threads try to share the same instance.
Naughty, naughty!
public void saveCustomerTicketUsingJDBC(String customerId) {
try {
getSession().getTransaction().begin(); //NOTHING HAPPENS AFTER THIS LINE OF CODE
.
.
} catch (Exception e) {
}
}
You should never (well, hardly ever) have an empty catch block, if there is a problem you will find that your code 'just simply dies' with no log messages. Oh look, that's what's happening ;)
At the very minimum you should log the exception, that will go a long way towards you helping you find what the problem is (and from there, the solution).

MSTest Unit Test - handling exceptions

I have a C# unit test using Selenium WebDriver to test to see if a link exists. Here's the code:
[TestMethod()]
public void RegisterLinkExistTest()
{
IWebElement registerLink = genericBrowserDriver.FindElement(By.PartialLinkText ("Register1"));
Assert.AreEqual("Register here", registerLink.Text, "Failed");
}
I wanted to see what happens if I set the PartialLinkText as "Register1" instead of "Register". MSTest failed this test with a exception thrown from Selenium. I wanted the Assert.AreEqual to execute but MSTest throws a exception on the previous line. I know I can use ExpectedException attribute to specify "OpenQA.Selenium.NoSuchElementException" but I don't want to do that way because I'm not expecting that exception. How do I go about handling this?
As #AD.Net already said, your test is working as expected.
You could catch the exception in case the link was not found but I don't see the point to do that. If the link is not found then the registerLink will be null. What's the point of asserting on a null object's property?
Your test works fine, just delete the Assert line.
However, if you also want to test the link's text try the following code:
[TestMethod()]
public void RegisterLinkExistTest()
{
try
{
IWebElement registerLink = genericBrowserDriver.FindElement(By.PartialLinkText ("Register1"));
Assert.AreEqual("Register here", registerLink.Text, "Register's link text mismatch");
}
catch(NoSuchElementException)
{
Assert.Fail("The register link was not found");
}
}
EDIT
You can seperate your test, the first test will check if the link exists and the second will assert it's properties.
[TestMethod()]
public void RegisterLinkExistTest()
{
IWebElement registerLink = genericBrowserDriver.FindElement(By.PartialLinkText ("Register1"));
}
[TestMethod()]
public void RegisterLinkTextTest()
{
IWebElement registerLink = genericBrowserDriver.FindElement(By.PartialLinkText ("Register1"));
Assert.AreEqual("Register here", registerLink.Text, "Register's link text mismatch");
}
Then use an OrderedTest and add them in that order so the RegisterLinkExistTest will be executed first. If it fails then the second test will not run.

Resources