I've repeatedly had problems with the DSL introduced by Grails in version 1.1 for configuring Log4J. My current configuration looks like this:
log4j = {
debug 'com.mypackages'
appenders {
console name: 'stdout', layout: pattern(conversionPattern: '%d{dd-MM-yyyy HH:mm:ss,SSS} %5p %c{1} - %m%n')
开发者_如何学编程 rollingFile name: 'hibeFile', file: "hibeFile", maxFileSize: '500KB'
}
// By default, messages are logged at the error level to both the console and hibeFile
root {
error 'stdout', 'hibeFile'
additivity = true
}
}
The intention here is:
- Log
com.mypackages
at the debug level and all others at the error level - Log all output to a file named hibeFile and the console
This works fine when I run the application or the integration tests. However, when I run the unit tests no logging appears either in the console, or in the "System.out" or "System.err" links shown in the Grails test report. How can I see my logs when running unit tests?
Thanks, Don
AFAIK, when running a Grails unit test, the whole logging is not available via log4j, the log.xxxx calls in domain classes etc. are just mocked using
mockLogging(ClassUnderTest, true)
The "true" stands for "enable debug". In order to do so, the unit test class must extend GrailsUnitTestCase. If you use mockController(class), it implicitly calls mockLogging(class, false) and therefore you get no debug logging. For details check out the grails sources, esp GrailsUnitTestCase and MockUtils.
In opposite to the above, in an integration test the whole machinery is started and log4j is available.
Here is a thought, you didn't ask this exactly but the same question was asked on the grails user group. I am posting my answer here as well, to spread the knowledge.
If you are explicitly saying def log = org.apache.commons.logging.LogFactory.getLog(this) in your classes rather than relying on dependency injection as was explained on the grails user group you can mock the getLog on the LogFactory.
The below is taken from grails.tests.MockUtils.mockLogging and modified to return the logger.
class LoggingEnabledTestCase extends GrailsUnitTestCase {
protected void setUp() {
super.setUp()
registerMetaClass(org.apache.commons.logging.LogFactory)
org.apache.commons.logging.LogFactory.metaClass.'static'.getLog = {instance ->
// This is taken from grails.tests.MockUtils and slightly changed to return a logger.
// Get the name of the class + the last component of the package
// (if it the class is in a package).
def pos = instance.class.name.lastIndexOf('.')
if (pos != -1) pos = instance.class.name.lastIndexOf('.', pos - 1)
def shortName = instance.class.name.substring(pos + 1)
// Dynamically inject a mock logger that simply prints the
// log message (and optional exception) to stdout.
def mockLogger = [
fatal: {String msg, Throwable t = null ->
println "FATAL (${shortName}): $msg"
if (t) {
println " Exception thrown - ${t.message}"
}
},
error: {String msg, Throwable t = null ->
println "ERROR (${shortName}): $msg"
if (t) {
println " Exception thrown - ${t.message}"
}
},
warn: {String msg, Throwable t = null ->
println "WARN (${shortName}): $msg"
if (t) {
println " Exception thrown - ${t.message}"
}
},
info: {String msg, Throwable t = null ->
println "INFO (${shortName}): $msg"
if (t) {
println " Exception thrown - ${t.message}"
}
},
debug: {String msg, Throwable t = null ->
println "DEBUG (${shortName}): $msg"
if (t) {
println " Exception thrown - ${t.message}"
}
},
trace: {String msg, Throwable t = null -> },
isFatalEnabled: {-> true},
isErrorEnabled: {-> true},
isWarnEnabled: {-> true},
isInfoEnabled: {-> true},
isDebugEnabled: {-> true},
isTraceEnabled: {-> false}] as Log
return mockLogger
}
}
protected void tearDown() {
super.tearDown()
}
}
Using Grails 1.1.1 and an approximation to your setup, I have a unit test called FooTests.groovy
After running grails test-app
, I am able to see the output from the test in the directory:
./test/reports/plain
specifically in the files, as appropriate:
TEST-com.mypackages.FooTests-err.txt
TEST-com.mypackages.FooTests-out.txt
TEST-com.mypackages.FooTests.txt
Note that I see no output in the hibeFile. I'm not sure, but I suspect a previous poster is correct in that unit tests don't receive the logging setup.
精彩评论