How can I execute try block statements in test case? My test case always goes to catch block.
I need to mock question bean, PostingResult, Question, dao all? I am confused. How I can test if/else ? Question class two fields are enums.
#Controller
#RequestMapping("/questionservice")
public class QuestionServiceController {
private static Log log = LogFactory.getLog(QuestionServiceController.class);
private final static Long SUCCESS = 000l;
private final static Long FAILURE = 999l;
#Autowired
QuestionAnswerDao questionAnswerDao;
#Autowired
QuestionAnswerDirectoryDao questionAnswerDirectoryDao;
#RequestMapping(value = "/postquestion", method = RequestMethod.POST)
public #ResponseBody PostingResult postQuestion(#RequestBody QuestionBean questionBean) {
System.out.println("In....");
PostingResult response = new PostingResult();
if (log.isDebugEnabled()) {
log.debug("QuestionBean: " + questionBean);
}
try {
System.out.println("in try");
Question question = questionAnswerDao.postQuestion(getQuestion(questionBean));
System.out.println("question"+question);
if (null != question) {
response.setStatus(SUCCESS);
response.setStatusMessage("Successfully saved..");
} else {
response.setStatusMessage("Question is null..");
response.setStatus(FAILURE);
}
} catch (Exception exp) {
if (log.isErrorEnabled()) {
log.error("Exception in processing " + questionBean + "; Exception: " + exp.toString());
}
response.setStatusMessage("Saving failed.. Exception: " + exp.toString());
response.setStatus(FAILURE);
}
return response;
}
It looks like you need to mock questionAnswerDao. Then tell Mockito to throw an exception when postQuestion() is invoked.
when(questionAnswerDao.postQuestion(/* specify args here */))
.thenThrow(new SomeException());
Then you can test the response object to see if it has the right messages and status.
Related
I have a class name HibernateSessionManager which have static method
public static HibernateSessionManager current;
I trying to mock
public Mbc_session getMBCSessionByGuid(String sessionGuid) {
try {
return HibernateSessionManager.current.withSession(hibernateSession -> {
return hibernateSession.get(Mbc_session.class, sessionGuid);
});
}
catch (Exception e) {
logger.error().logFormattedMessage(Constants.MBC_SESSION_GET_ERROR_STRING,
e.getMessage()); throw new DAOException(ErrorCode.MBC_1510.getCode(), ErrorCode.MBC_1510.getErrorMessage() + ",Operation: getMBCSessionByGuid");
}
}
i am using following function in #before
public static void initMocks(Session session) {
HibernateSessionManager.current = mock(HibernateSessionManager.class,Mockito.RETURNS_DEEP_STUBS);
HibernateTransactionManager.current = mock(HibernateTransactionManager.class,Mockito.RETURNS_DEEP_STUBS);
doCallRealMethod().when(HibernateTransactionManager.current).withTransaction(any(), any());
doCallRealMethod().when(HibernateSessionManager.current).withSession(any(Consumer.class));
// Mockito.when(HibernateSessionManager.current.withSession((Consumer<Session>) any(Function.class))).thenCallRealMethod();
when(HibernateSessionManager.current.getSession()).thenReturn(session);
}
My test case is following
#Test public void test_getMBCSessionByGuid() {
Mbc_session mbcSession = new Mbc_session();
String sessionGuid = "session GUID";
when(HibernateSessionManager.current.getSession()).thenReturn(session);
// when(sessionFactory.getCurrentSession()).thenReturn(session);
when(session.get(Mbc_session.class, sessionGuid)).thenReturn(mbcSession);
Mbc_session mbcSession2 = mbc_sessionDao.getMBCSessionByGuid(sessionGuid);
assertNull(mbcSession2);
}
it passed but coverage is not touching following code
return hibernateSession.get(Mbc_session.class, sessionGuid);
here is my withSession code
public void withSession(Consumer<Session> task) {
Session hibernateSession = getSession();
try {
task.accept(hibernateSession);
} finally {
HibernateSessionManager.current.closeSession(hibernateSession);
}
}
openSession
public Session getSession() {
Session threadCachedSession = threadSession.get();
if (threadCachedSession != null) {
if (!threadCachedSession.isOpen()) { throw new
IllegalStateException("Session closed outside of
HibernateSessionManager.");
}
return threadCachedSession;
} return sessionFactory.openSession();
}
Looking at the code and assuming it compiles, I believe the problem is that you have two withSession(...) methods and in the code posted you are trying to mock the wrong one. Here are their signatures:
// You should NOT mock this one
void withSession(Consumer<Session> task) {
...
}
// You should mock this one instead
Mbc_session withSession(Function<Session, Mbc_session> task) {
...
}
It was easy to guess as the getMBCSessionByGuid method contains the snippet below with the Function<Session, Mbc_session> being passed as an argument to withSession(...) instead of Consumer<Session>:
return HibernateSessionManager.current.withSession(hibernateSession -> {
// something is returned which means a Function is passed, not a Consumer
return hibernateSession.get(Mbc_session.class, sessionGuid);
});
As an easy fix, you can just add the following to the test:
doCallRealMethod().when(HibernateSessionManager.current).withSession(any(Function.class));
and remove the existing mock configuration with a Consumer:
doCallRealMethod().when(HibernateSessionManager.current).withSession(any(Consumer.class));
P.S. Just in case, I can easily reproduce the issue on my machine.
This question already has an answer here:
How to use mock in a private static final variable in Spock?
(1 answer)
Closed 5 months ago.
How to test the below java catch block where in catch() doesnt throw exception back.
class ErrorTransImpl {
private static final Logger logger = Logger.getLogger(ErrorTransImpl.class);
public int errorCatcher(ErrorTrans transError){
int ct = 0;
if (transError != null){
String query = "INSERT INTO tab_1 (rw1,rw2,rw3,rw4,rw5) VALUES (?,?,?,?,?)";
try {
ct = jdbcTemplate.update(query, new Object[] {transError.col1(),transError.col2(), transError.col3(),transError.col4(),transError.col5()});
}catch (DataAccessException ex) {
logger.error(ex);
}
}
return ct;
}
}
I tried testing as below, but:
1>Unable to get into catch block.
2> Unable to test catch() even if inside as it doesnt throw exception back.
def 'throw DataAccess Exception upon incorrect update'() {
given:
def log = Mock(Logger)
def originalLogger = ErrorTransImpl.logger
ErrorTransImpl.logger = log
ErrorTransImpl errTransImpl = Spy() {
jdbcTemplate >> {
throw new DataAccessException() {
#Override
String getMessage() {
return super.getMessage()
}
}
}
}
when:
errTransImpl.errorCatcher(new ErrorTrans())
then:
// thrown DataAccessException
//Not sure what to assert or test here ??
}
Can anyone help on how i test this?
You need to test the behaviour that
ct = jdbcTemplate.update(query, new Object[] {transError.col1(),transError.col2(), transError.col3(),transError.col4(),transError.col5()});
failed. Or, I don't really like this myself, you can check that the logger.error() was called.
I'm trying to use #Retryable on a method that calls the REST template. If an error is returned due to a communication error, I want to retry otherwise I want to just thrown an exception on the call.
When the ApiException occurs, instead of it being thrown and ignored by #Retryable, I get an ExhaustedRetryException and a complaint about not finding enough 'recoverables', i.e, #Recover methods.
I thought I'd see if just having the recoverable method present might make it happy and still perform as hoped for. Not so much. Instead of throwing the exception, it called the recoverable method.
#Retryable(exclude = ApiException include = ConnectionException, maxAttempts = 5, backoff = #Backoff(multiplier = 2.5d, maxDelay = 1000000L, delay = 150000L))
Object call(String domainUri, ParameterizedTypeReference type, Optional<?> domain = Optional.empty(), HttpMethod httpMethod = HttpMethod.POST) throws RestClientException {
RequestEntity request = apiRequestFactory.createRequest(domainUri, domain, httpMethod)
log.info "************************** Request Entity **************************"
log.info "${request.toString()}"
ResponseEntity response
try {
response = restTemplate.exchange(request, type)
log.info "************************** Response Entity **************************"
log.info "${response.toString()}"
} catch (HttpStatusCodeException | HttpMessageNotWritableException httpException) {
String errorMessage
String exceptionClass = httpException.class.name.concat("-")
if(httpException instanceof HttpStatusCodeException) {
log.info "************************** API Error **************************"
log.error("API responded with errors: ${httpException.responseBodyAsString}")
ApiError apiError = buildErrorResponse(httpException.responseBodyAsString)
errorMessage = extractErrorMessage(apiError)
if(isHttpCommunicationError(httpException.getStatusCode().value())) {
throw new ConnectionException(exceptionClass.concat(errorMessage))
}
}
errorMessage = StringUtils.isBlank(errorMessage) ? exceptionClass.concat(httpException.message) : exceptionClass.concat(errorMessage)
throw new ApiException(httpMethod, domainUri, errorMessage)
}
if (type.type == ResponseEntity) {
response
}
else response.body
}
#Recover
Object connectionException(ConnectionException connEx) {
log.error("Retry failure - communicaiton error")
throw new ConnectionException(connEx.class.name + " - " + connEx.message)
}
Any insights would be appreciated. Is it a bug or operator error?
This is using Spring Boot 1.3.6 and Spring-Retry 1.1.3.
Your include/exclude syntax looks bad - that won't even compile.
I just wrote a quick test and it works exactly as expected if you have zero #Recover methods...
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.annotation.Retryable;
#SpringBootApplication
#EnableRetry
public class So38601998Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(So38601998Application.class, args);
Foo bean = context.getBean(Foo.class);
try {
bean.out("foo");
}
catch (Exception e) {
System.out.println(e);
}
try {
bean.out("bar");
}
catch (Exception e) {
System.out.println(e);
}
}
#Bean
public Foo foo() {
return new Foo();
}
public static class Foo {
#Retryable(include = IllegalArgumentException.class, exclude = IllegalStateException.class,
maxAttempts = 5)
public void out(String foo) {
System.out.println(foo);
if (foo.equals("foo")) {
throw new IllegalArgumentException();
}
else {
throw new IllegalStateException();
}
}
}
}
Result:
foo
foo
foo
foo
foo
java.lang.IllegalArgumentException
bar
java.lang.IllegalStateException
If you just add
#Recover
public void connectionException(IllegalArgumentException e) {
System.out.println("Retry failure");
}
You get
foo
foo
foo
foo
foo
Retry failure
bar
org.springframework.retry.ExhaustedRetryException: Cannot locate recovery method; nested exception is java.lang.IllegalStateException
So you need a catch-all #Recover method...
#Recover
public void connectionException(Exception e) throws Exception {
System.out.println("Retry failure");
throw e;
}
Result:
foo
foo
foo
foo
foo
Retry failure
bar
Retry failure
java.lang.IllegalStateException
First of all the final purpose is that i'm trying to inject a DAO connection into an SMD context (Ajax) so i'll ensure that transactions are being Commited (or Rollback), my problem is that i'm not being able to know if the invoke() method throws an exception,
I have the following Interceptor:
public class SomeInterceptor implements Interceptor {
private static final long serialVersionUID = 1L;
#Override
public String intercept(ActionInvocation invocation) {
String result = "";
GenericDAO dao = new GenericDAO();
try {
dao.begin();
invocation.getInvocationContext().put("contextDao", dao);
result = invocation.invoke();
//attempt to solve
Object exception = invocation.getInvocationContext().getValueStack().findValue("exception");
if (exception != null && exception instanceof Exception){
dao.rollback();
} else {
dao.commit();
}
} catch (Exception ex) {
dao.rollback();
System.out.println("ROLLBACK!");
ex.printStackTrace();
} finally {
dao.close();
}
return result;
}
}
The line "attempt to solve" is based on this question. Inside the invoke i'm just throwing a NullPointerException, the result right now is that the exception is being catch before the catch at the Interceptor, however is not a catch that i had set,
#SMDMethod
public HashMap<String,String> someMethod() {
IGenericDAO dao = (IGenericDAO) ActionContext.getContext().get("contextDao");
//dao's deletes, updates that i want to rollback
HashMap<String,String> x = null;
x.put("x","x"); //<---- NPE!
return null;
}
I want ActionInvocation.invoke() to throw the exception so i'll know i need to rollback the DB session. Any approach who succeed this purpose is welcome,
Edit 1:
I've found this question that does almost the same as me but i dont understand how is using rollback (at my point of view is always doing rollback)
Greetings
I didn't found any way to achieve my goal as i wanted, instead i've solved the scenario by doing this:
public class SomeInterceptor implements Interceptor {
private static final long serialVersionUID = 1L;
#Override
public String intercept(ActionInvocation invocation) {
String result = "";
GenericDAO dao = new GenericDAO();
try {
dao.begin();
invocation.getInvocationContext().put("contextDao", dao);
result = invocation.invoke();
dao.rollback();
} catch (Exception ex) {
dao.rollback();
System.out.println("ROLLBACK!");
ex.printStackTrace();
} finally {
dao.close();
}
return result;
}
}
Yes... i removed "commit" instruction at interceptor, instead now im forced to do "commit" at the end of any call that uses the mentioned DAO,
#SMDMethod
public HashMap<String,String> someMethod() {
IGenericDAO dao = (IGenericDAO) ActionContext.getContext().get("contextDao");
//dao's deletes, updates that i want to rollback
HashMap<String,String> x = null;
x.put("x","x"); //<---- NPE!
dao.commit(); //<---- COMMIT!
return null;
}
I dont like this solution but it was all i was able to do. I came out with this like 1 day after posted the question, i waited for an answer until now,
Hope it helps someone,
I have this program as shown below , right now its only printng the stacktrace .
my question is that , is it possible to get the stack trace and also a custom field , here in my case i need 1090099
Please tell me if its possible ??
package com;
import org.apache.log4j.Logger;
public class Test {
private static final Logger logger = Logger.getLogger(Test.class);
public static void main(String args[]) {
try {
String accountid = "1090099";
String desc = null;
System.out.println(desc.toUpperCase());
}
catch (Exception t)
{
logger.fatal("Exception inside the Test program ", t);
}
}
}
2013-06-26 21:44:29,723[main] FATAL(Test.java:<main>:16)- Exception inside the Test program
java.lang.NullPointerException
at com.Test.main(Test.java:12)
You have to include it manually in the message you're logging. But it looks to me like what you're really looking for is the MDC (mapped diagnostic context), a way to store values in a thread-local "context" that can then be used to distinguish between log messages relating to different application-level entities.
package com;
import org.apache.log4j.*;
public class Test {
private static final Logger logger = Logger.getLogger(Test.class);
public static void main(String args[]) {
MDC.put("accountid", "1090099");
try {
String desc = null;
System.out.println(desc.toUpperCase());
}
catch (Exception t)
{
logger.fatal("Exception inside the Test program ", t);
} finally {
MDC.remove("accountid");
}
}
}
You would then include %X{accountid} somewhere in your appender's layout pattern and it would include the appropriate MDC entry in every log message, including those logged by third-party code that you call.
I would create my own Exception class, with members to hold the additional information, and a suitable toString() method that displays them. Wrap the original Exception in your custom Exception and add the information you want preserved.
Yes, you can print the value as long as it's in scope.
String accountid = null;
try {
accountid = "1090099";
String desc = null;
System.out.println(desc.toUpperCase());
} catch (Exception t) {
logger.fatal("Exception inside the Test program " + accountid, t);
}
Also, I would suggest using logger.debug instead of system.out.println for your other logging calls...
You are close to achieving that.
In your case you will have to declare the accountid outside the try block and then you can append the accountid along with your Exception inside the Test program message`
String accountid = "";
try {
accountid = "1090099";
String desc = null;
System.out.println(desc.toUpperCase());
}
catch (Exception t)
{
logger.fatal("Exception inside the Test program.\nAccount ID: " + accountid, t);
}