How Can I log exception stacktrace via custom junit runner? - exception

Hi I have custom junit runner
public class InterceptorRunner extends BlockJUnit4ClassRunner {
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface InterceptorClasses {
public Class<?>[] value();
}
public InterceptorRunner(Class<?> klass) throws InitializationError {
super(klass);
}
#Override
public Statement methodInvoker(FrameworkMethod method, Object test) {
InterceptorStatement statement = new InterceptorStatement(super.methodInvoker(method, test));
InterceptorClasses annotation = test.getClass().getAnnotation(InterceptorClasses.class);
Class<?>[] klasez = annotation.value();
try {
for (Class<?> klaz : klasez) {
statement.addInterceptor((Interceptor) klaz.newInstance());
}
} catch (IllegalAccessException ilex) {
ilex.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return statement;
}
#Override
public void run(RunNotifier notifier) {
FailListener listener = new FailListener();
notifier.addListener(listener);
super.run(notifier);
notifier.removeListener(listener);
}
}
and custom listener
public class FailListener extends RunListener {
#Override
public void testFailure(Failure failure) throws Exception {
System.out.println("test fails");
super.testFailure(failure);
}
public void testStarted(Description description) throws Exception {
System.out.println("Test started");
super.testStarted(description);
}
}
How can I log not only System.out.println("test fails"); but also Exception and some other information?
It seems to me that it possible to use failure, but I don't know how to.

The Failure object has a method getException().

Related

How to test Kafka OnFailure callback with Junit?

I have the following code to send data to Kafka:
#Service
public class KafkaSender{
#Autowired
private KafkaTemplate<String, Employee> kafkaTemplate;
public void sendMessage(Employee employee) {
ObjectMapper objectMapper = new ObjectMapper();
ListenableFuture<SendResult<String, Employee>> listenableFuture = kafkaTemplate.send(topic,employee);
listenableFuture.addCallback(new ListenableFutureCallback<SendResult<String, Employee>>() {
#Override
public void onSuccess(SendResult<String, Employee> result) {
// method to save in DB
saveInDatabaseMethod(result.getProducerRecord());
}
#Override
public void onFailure(Throwable ex) {
// class cast exception occur here
ProducerRecord<String, Employee> producerRecord = ((KafkaProducerException) ex).getFailedProducerRecord();
saveInDatabaseMethod(producerRecord);
}
}
}
}
I am able to test the OnSucess callback scenario, but i am not able to test the OnFailure one.
#Test
void test() throws InterruptedException, ExecutionException {
Throwable ex = mock(Throwable.class);
Employee employee = new Employee();
when(kafkaTemplate.send(null,employee )).thenReturn(responseFuture);
when(sendResult.getProducerRecord()).thenReturn(producerRecord);
when(producerRecord.value()).thenReturn(employee);
doAnswer(invocationOnMock -> {
ListenableFutureCallback<SendResult<String, Employee>> listenableFutureCallback = invocationOnMock.getArgument(0);
listenableFutureCallback.onFailure(ex);
return null;
}).when(responseFuture).addCallback(any(ListenableFutureCallback.class));
kafkaSender.sendMessage(employee);
}
The above test throws:
java.lang.ClassCastException:
org.mockito.codegen.Throwable$MockitoMock$2137573915 cannot be cast to
org.springframework.kafka.core.KafkaProducerException
ProducerRecord<String, Employee> producerRecord = ((KafkaProducerException) ex).getFailedProducerRecord();
Your mock is not calling the callback with a KPE, its calling it with this
Throwable ex = mock(Throwable.class);
You need to wrap it in a KPE.

I need to write JUNIT for Apache camel route

I have camel route as below
public class IncomingBatchFileRoute extends RouteBuilder {
#Value(CCS_PROCESSING_INCOMING_DIRECTORY)
private String source;
#Override
public void configure() throws Exception {
from(sourceLocation)).autoStartup(false).to("encryptionEndPoint");
}
}
I need to write a JUNIT For above camel route and am new to it and created a structure as below
public class IncomingBatchFileRouteTest extends CamelTestSupport{
#Override
public RoutesBuilder createRouteBuilder() throws Exception {
return new IncomingBatchFileRoute();
}
#Test
public void sampleMockTest() {
}
}
Not sure how to complete it. Request you to help me on this
You need to mock your encryptionEndPoint and start your route with a producerTemplate
#Produce(uri = CCS_PROCESSING_INCOMING_DIRECTORY)
protected ProducerTemplate template;
#EndpointInject(uri = "encryptionEndPoint")
protected MockEndpoint resultEndpoint;
#Test
public void sampleMockTest() {
// GIVEN
this.resultEndpoint.expectedMessageCount(1);
// WHEN
this.template.sendBody("Hey");
// THEN
this.resultEndpoint.assertIsSatisfied();
}

catch exception if boolean is false

This is the easiest example of a complex issue. I haven't found the example of this problem anywhere in the entire internet. I'm validating the input in a validationMethod that return Boolean. Now, I need to use this method in calling class (run the flow if return is true, catch exception if return is false).
public class StringUtil{
public static boolean validateNumInput(String UserInput)
{
if(UserInput.matches("[0-9]+")){
return true;
} return false;
}
}
public class Main{
public static void main(String[] args){
String a="012*+";
try{
if(StringUtil.validateNumInput(a)){
System.out.println(StringUtil.validateNumInput(a));
}
}catch(Exception e){
System.out.println("Big problem");
}
}
}
According to the documentation, you can filter catch clauses with a Boolean predicate. So, your validation method would need to throw an exception which you could filter for in your catch clause. But if you're doing that, you might as well roll your own custom exception and not have to deal with the Boolean at all. The other alternative is, in your calling code, treat the return code as a return code and throw your own exception.
Option 1:
public class StringUtil{
public static boolean validateNumInput(String UserInput)
{
if(UserInput.matches("[0-9]+")){
return true;
}
throw new Exception ("Validation failed!");
}
}
public class Main{
public static void main(String[] args){
String a="012*+";
try{
if(StringUtil.validateNumInput(a)){
System.out.println(StringUtil.validateNumInput(a));
}
}catch(Exception e) when (e.Message == "Validation failed!") {
System.out.println("Big problem");
}
}
}
Option 2:
public class Main{
public static void main(String[] args){
String a="012*+";
try{
if(StringUtil.validateNumInput(a)){
System.out.println(StringUtil.validateNumInput(a));
} else {
throw new Exception ();
}
}catch(Exception e) {
System.out.println("Big problem");
}
}
}

How can I replace JSON Converter with my own

I'm looking to use JACKSON instead of grails JSON ,without changing the auto-scaffolded contollers.
Is it possible to seamlessly replace the current grails JSON converter with another one ?
Are there any classes to implement other then AbstractConverter...
Should be pretty simple. AbstractConverter is all you need to extend to do:
render result as JackSON
Something like this***:
*** taken from here: https://github.com/sjhorn/grails-jackson/blob/master/src/groovy/com/hornmicro/JackSON.groovy
class JackSON extends AbstractConverter {
Object target
public JackSON() {
}
public JackSON(Object target) {
this()
setTarget(target)
}
public void render(Writer out) throws ConverterException {
try {
ObjectMapper mapper = new ObjectMapper()
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
mapper.configure(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM, false)
mapper.configure(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT, false)
mapper.writeValue(out, target)
} catch(e) {
throw new ConverterException(e)
}
try {
out.flush()
out.close()
} catch (Exception e) {
log.warn("Unexpected exception while closing a writer: " + e.getMessage())
}
}
public void render(HttpServletResponse response) throws ConverterException {
response.setContentType(GrailsWebUtil.getContentType("application/json", "UTF-8"));
try {
render(response.getWriter())
} catch (IOException e) {
throw new ConverterException(e)
}
}
public Object getWriter() throws ConverterException {
throw new ConverterException("Not Implemented")
}
public void convertAnother(Object o) throws ConverterException {
throw new ConverterException("Not Implemented")
}
public void build(Closure c) throws ConverterException {
throw new ConverterException("Not Implemented")
}
public ObjectMarshaller lookupObjectMarshaller(Object target) {
return null
}
public void setTarget(Object target) {
this.target = target
}
}

CustomException with error code

I have created a CustomException with a custom message and an error code.
public class CustomException extends RuntimeException{
private int errorCode;
public CustomException(String message,int errorCode){
super(message);
this.errorCode=errorCode;
}
public int getErrorCode(){
return this.errorCode;
}
public String getMessage(){
return "Message: "+super.getMessage()+" ErrorCode: "+this.errorCode;
}
}
When I add a null value in a list throw CustomException with the message "Null" and error Code 1. When I add an empty value the message for exception is "Empty" and error Code 2.
How I can capture and test error code in unit test?
I have done something like that:
public class MyListTester{
private Class exceptionType = CustomException.class;
#Test
public void testAddNonNullValue() {
exception.expect(exceptionType);
exception.expectMessage("Null");
list.add(null);
}
but I don't have acces to the error code
The trick is to use the expect method of the ExpectedException rule which takes a Matcher as parameter and to write a custom matcher for verifying the error code. Here is a complete example:
public class MyListTester {
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void testAddNullValue() {
MyList list = new MyList();
exception.expect(CustomException.class);
exception.expectMessage("Null");
exception.expect(errorCode(1));
list.add(null);
}
#Test
public void testAddEmptyValue() {
MyList list = new MyList();
exception.expect(CustomException.class);
exception.expectMessage("Empty");
exception.expect(errorCode(2));
list.add(emptyValue);
}
private Matcher<? extends CustomException> errorCode(final int errorCode) {
return new CustomTypeSafeMatcher<CustomException>("errorCode " + errorCode) {
#Override
protected boolean matchesSafely(CustomException e) {
return e.getErrorCode() == errorCode;
}
};
}
}