Log4j in Unit Testing Environment - java

I am performing JUnit Testing and receiving log4j:WARN No appenders could be found for logger (class .. ) error when I run test class(s).
Log4j properties file is present inside my folder root directory.
This code seems to work but why doesn't log4j picked up automatically.
package com.folio3.automation;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.junit.Test;
import junit.framework.Assert;
public class TestClass {
static {
BasicConfigurator.configure();
}
private static final Logger LOG = Logger.getLogger(TestClass.class);
#Test
public void test1(){
LOG.info("test 1 called ");
Assert.assertEquals(true, false);
}
}
Do I have to call BasicConfigurator.configure(); in every class or Base class ?
Is there any way to achieve?

Try adding your application root directory to your VM start command and your problem will disappear.

Related

Java logging question. It doesn't work out. Cannot find the reason

Error here?
It doesn't work out and I cannot get the reason :(
import java.util.logging.Logger;
public class LoggingTest {
public static void main(String[] args) {
String filename = "test.dat";
Logger.getGlobal().info(filename+"opened file");
}
}
I think you should add
java.util.logging.FileHandler
java.util.logging.ConsoleHandler
to
java.util.logging.Logger
or there will be no output in neither console nor log file.
Add this import - import java.util.logging.FileHandler;
Then add file handler before logging info:
FileHandler fileHandler = new FileHandler("test.dat", true);
Logger.getGlobal().addHandler(fileHandler);

Running pact jvm provider tests via IntelliJ

I am very trying the pact-jvm-provider-junit using IntelliJ IDEA as my IDE.
I'm testing out the provided ContractTest example:
import org.junit.BeforeClass;
import org.junit.Before;
import org.junit.ClassRule;
import au.com.dius.pact.provider.junit.State;
import au.com.dius.pact.provider.junit.Provider;
import au.com.dius.pact.provider.junit.target.TestTarget;
import au.com.dius.pact.provider.junit.target.Target;
import au.com.dius.pact.provider.junit.target.HttpTarget;
import au.com.dius.pact.provider.junit.TargetRequestFilter;
import org.apache.http.HttpRequest;
import au.com.dius.pact.provider.junit.PactRunner;
import au.com.dius.pact.provider.junit.loader.PactFolder;
import au.com.dius.pact.provider.junit.loader.PactUrl;
import au.com.dius.pact.provider.junit.VerificationReports;
import com.github.restdriver.clientdriver.ClientDriverRule;
import org.junit.runner.RunWith;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import static com.github.restdriver.clientdriver.RestClientDriver.giveEmptyResponse;
import static com.github.restdriver.clientdriver.RestClientDriver.onRequestTo;
#RunWith(PactRunner.class) // Say JUnit to run tests with custom Runner
#Provider("uicc_repository") // Set up name of tested provider
//#PactFolder("rs") // Point where to find pacts (See also section Pacts source in documentation)
#PactUrl(urls = {"file:///C:/IdeaProjects/src/pack-test-provider/resources/test_consumer-test_provider.json"}) // Point where to find pacts (See also section Pacts source in documentation)
#VerificationReports(value = {"markdown","json"}, reportDir = "C:/IdeaProjects/src/pack-test-provider/resources")
public class ContractTest {
// NOTE: this is just an example of embedded service that listens to requests, you should start here real service
#ClassRule //Rule will be applied once: before/after whole contract test suite
public static final ClientDriverRule embeddedService = new ClientDriverRule(6060);
private static final Logger LOGGER = LoggerFactory.getLogger(ContractTest.class);
#BeforeClass //Method will be run once: before whole contract test suite
public static void setUpService() {
//Run DB, create schema
//Run service
//...
}
#Before //Method will be run before each test of interaction
public void before() {
// Rest data
// Mock dependent service responses
// ...
embeddedService.addExpectation(
onRequestTo("/data"), giveEmptyResponse()
);
}
#TestTarget // Annotation denotes Target that will be used for tests
public final Target target = new HttpTarget(6060); // Out-of-the-box implementation of Target (for more information take a look at Test Target section)
#State("default") // Method will be run before testing interactions that require "default" or "no-data" state
public void toDefaultState() {
// Prepare service before interaction that require "default" state
// ...
System.out.println("Now service in default state");
LOGGER.info("Now service in default state");
}
}
But when I try to run the test (Run -> Run ContractTest), it's like the test is not ran at all:
Mar 15, 2017 3:24:00 PM org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry loadTestEngines
INFO: Discovered TestEngines with IDs: [junit-jupiter, junit-vintage]
Mar 15, 2017 3:24:01 PM org.junit.vintage.engine.execution.TestRun lookupTestDescriptor
WARNING: Runner au.com.dius.pact.provider.junit.PactRunner on class rs.ContractTest reported event for unknown Description: rs.ContractTest. It will be ignored.
Process finished with exit code 0
enter image description here
I am not sure if it's an issue with how I am running the test in IntelliJ or I am missing something in the pact-jvm-provider "runner".
Appreciate any help on this topic.
Thanks!

How-to catch "log4j:WARN No appenders could be found for logger"?

I want to handle this error to set up an alternative configuration log4j. Is that possible?
I don't have any stacktrace, only log's warnings
log4j:WARN No appenders could be found for logger (agent.Test1Agent.JavaAgent).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
There is no way to do what you want correctly because log4j doesn't throw any exceptions or notifies somehow in case of misconfiguration. But it is possible.
See PoC below
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.spi.Configurator;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URL;
public class Log4jAlternativeConfig {
private static class PrintStreamCallbackSupportDecorator extends PrintStream {
public PrintStreamCallbackSupportDecorator(OutputStream out, Callback callback) {
super(out);
this.callback = callback;
}
public interface Callback {
public void onPrintln(String x);
}
private Callback callback;
#Override
public void println(String x) {
callback.onPrintln(x);
super.println(x);
}
}
public static void main(String[] args) {
PrintStreamCallbackSupportDecorator.Callback callback = new PrintStreamCallbackSupportDecorator.Callback() {
#Override
public void onPrintln(String x) {
if (x.startsWith("log4j:WARN No appenders could be found for logger")) {
Configurator configurator = new PropertyConfigurator();
URL url = Loader.getResource("log4j_alternative.properties");
configurator.doConfigure(url, LogManager.getLoggerRepository());
}
}
};
System.setErr(new PrintStreamCallbackSupportDecorator(System.err, callback));
Logger log = LogManager.getLogger(Log4jAlternativeConfig.class);
//causes "No appenders could be found for logger" warning
log.error("test");
//should be logged as configured in log4j_alternative.properties
log.error("test 2");
}
}
The solution isn't perfect but it works.
You can setup an alternative log4j configuration by providing a default configuration file on your classpath. Since log4j uses Thread.getContextClassLoader().getResource() to locate the default configuration files and does not directly check the file system, it should be included in your jar. So that if no external configuration provided it will fall back on the default configuration.
See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info

How to run Spring Shell scripts in a JUnit test

I have a Spring Shell-based application and a couple of scripts. Is there an easy way to run the scripts in a JUnit test such that a test fails, if some exception/error occurs during the execution of the script?
The purpose of the tests is to make sure that all correct scripts run without errors.
Update 1:
Here's a little helper class for running scripts in JUnit:
import org.apache.commons.io.FileUtils;
import org.springframework.shell.Bootstrap;
import org.springframework.shell.core.CommandResult;
import org.springframework.shell.core.JLineShellComponent;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static org.fest.assertions.api.Assertions.*;
public class ScriptRunner {
public void runScript(final File file) throws IOException
{
final Bootstrap bootstrap = new Bootstrap();
final JLineShellComponent shell = bootstrap.getJLineShellComponent();
final List<String> lines = FileUtils.readLines(file);
for (final String line : lines) {
execVerify(line, shell);
}
}
private void execVerify(final String command, final JLineShellComponent shell) {
final CommandResult result = shell.executeCommand(command);
assertThat(result.isSuccess()).isTrue();
}
}
You can create an instance of Bootstrap, get the shell out of it and then executeCommand() (including the shell command) on it.
You may be interested in what is done in Spring XD for this: https://github.com/spring-projects/spring-xd/blob/master/spring-xd-shell/src/test/java/org/springframework/xd/shell/AbstractShellIntegrationTest.java (although there are a lot of XD specific details)

How to use S3DistCp in java code

I want to copy output of job from EMR cluster to Amazon S3 pro-grammatically.
How to use S3DistCp in java code to do the same.
hadoop ToolRunner can run this.. since S3DistCP extends Tool
Below is the usage example:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.util.ToolRunner;
import com.amazon.external.elasticmapreduce.s3distcp.S3DistCp
public class CustomS3DistCP{
private static final Log log = LogFactory.getLog(CustomS3DistCP.class);
public static void main(String[] args) throws Exception {
log.info("Running with args: " + args);
System.exit(ToolRunner.run(new S3DistCp(), args));
}
you have to have s3distcp jar in your classpath
You can call this program from a shell script.
Hope that helps!

Categories

Resources