0

I want to make "logger.isDebugEnabled()" from groovy spock.Such as

logger.isDebugEnabled() >> false

my code is

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.PropertyResolver;

public class Sample{
    public static final Logger logger = LoggerFactory.getLogger(Sample.class);

   public void checkForAllRequiredProperties(String scope) {

       if (logger.isDebugEnabled()) {
            logger.debug("some message ");
        }

    }
}

but logger is private static final i not able mocking logger.isDebugEnabled()

Jeff Scott Brown
  • 26,804
  • 2
  • 30
  • 47
sajeeth
  • 47
  • 2
  • 9
  • Is `Sample` written in Java or Groovy? The code shown there looks like Java but is also valid Groovy, and if it is Groovy then you have options that you don't have if it is Java. – Jeff Scott Brown May 31 '22 at 14:58
  • @jeffScottBrown thanks .Test case in groovy. `logger.isDebugEnabled() >> false` . – sajeeth May 31 '22 at 15:08
  • "Test case in groovy." - I am not asking about the test. I am asking about `Sample`. – Jeff Scott Brown May 31 '22 at 15:14
  • "but logger is private static final i not able mocking logger.isDebugEnabled()" - Those 2 claims are unrelated. The fact that `logger` is `private`, doesn't keep the method from being mocked, neither does `static` or `final`. Methods on `private`, `static`, and `final` members can definitely be mocked. – Jeff Scott Brown May 31 '22 at 15:17
  • yup @JeffScottBrown how to make `logger.isDebugEnabled()` as false any suggestion. – sajeeth May 31 '22 at 15:28
  • @JeffScottBrown sample is Java code and Test case in Groovy spock. – sajeeth May 31 '22 at 15:30
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/245208/discussion-between-sajeeth-and-jeff-scott-brown). – sajeeth May 31 '22 at 15:32
  • Are you opposed to engaging Mockito? – Jeff Scott Brown May 31 '22 at 15:33
  • no i am using Mock @JeffScottBrown – sajeeth May 31 '22 at 15:34
  • "no i am using Mock" - I was asking about Mockito in particular. Are you saying that you tried Mockito and had couldn't make it work? – Jeff Scott Brown May 31 '22 at 15:39
  • Does this answer your question? [Mocking Logger and LoggerFactory with PowerMock and Mockito](https://stackoverflow.com/questions/8948916/mocking-logger-and-loggerfactory-with-powermock-and-mockito) – Jeff Scott Brown May 31 '22 at 15:40
  • yes Same as @JeffScottBrown but need solution in Groovy spock. – sajeeth May 31 '22 at 15:48
  • " but need solution in Groovy spock." - that solution works fine with Spock. – Jeff Scott Brown May 31 '22 at 15:49
  • If what you mean is you want to use a Spock mock for that property in particular, I don't know of any way to do that since `Sample` is written in Java. Best of luck! – Jeff Scott Brown May 31 '22 at 15:49
  • Does this answer your question? [make logger.isDebugEnabled() false in Groovy](https://stackoverflow.com/questions/72426560/make-logger-isdebugenabled-false-in-groovy) – Leonard Brünings May 31 '22 at 22:48
  • @JeffScottBrown FYI https://github.com/joke/spock-mockable is a better alternative to powermock, it selectively removes `final` from the listed classes. – Leonard Brünings May 31 '22 at 22:51
  • "it selectively removes final from the listed classes" - great. The final often doesn't have to be removed but of course there are times when that is helpful. In the case cited in the question, `final` isnt' a problem if one mocks the call to `getLogger()`. `final` is fine in that case because the reference never changes. Thank you for sharing your feedback! – Jeff Scott Brown Jun 01 '22 at 12:38
  • Instead of trying to mock/stub the logger, which would require you to use extra tools like Mockito, Sarek or PowerMock, why don't you just set the log level you need for your test case via configuration for your logging tool? And why do you use `if (logger.isDebugEnabled())`? Shouldn't logging to the desired level make sure that only info is being logged which you want to be? – kriegaex Jun 04 '22 at 10:02
  • You might also be interested in [this solution](https://stackoverflow.com/a/71248053/1082681) I suggested a while ago: Instead of mocking the logger, simply add a mock appender and verify interactions on that one. this does not solve your requirement to stub `isDebugEnabled()`, but if you simply do not use that `if` condition anymore, it will not be a problem any longer. Anyway, there are several ways to approach this, see my first suggestion about configuring the log level before running the test. – kriegaex Jun 04 '22 at 10:09

1 Answers1

1

You can use slf4j-test which gives you access to a TestLogger that you can then use to set the desired logging level and also inspect the logged messages. See the website for usage examples.

import spock.lang.*
import uk.org.lidalia.slf4jtest.TestLogger
import uk.org.lidalia.slf4jtest.TestLoggerFactory

import static uk.org.lidalia.slf4jtest.LoggingEvent.*

class ASpec extends Specification {
  TestLogger logger = TestLoggerFactory.getTestLogger(Sample)

  def "a test" () {
    given:
    // will only enable error level
    logger.setEnabledLevels(Level.ERROR) 

    when:
    // ...

    then:
    logger.getLoggingEvents() == [debug("some message ")]
  }
}

You might want to separate those logging tests into a separate test target, so that the rest uses the normal logging infrastructure, or don't depending on how extensive you test logging.

Leonard Brünings
  • 12,408
  • 1
  • 46
  • 66
  • 1
    The logger in this example is declared within the spec, not within the class under test (CUT). herefore, it does not answer the question how to mock/stub the logger there. In order for the test logger to be helpful, the public final static logger in the CUT would have to be non-final. I know you mentioned the Spock-Mockable utility somewhere in a comment, but this answer does not show how to use the two tools in question together, i.e. how to inject the test logger into the CUT. – kriegaex Jun 04 '22 at 09:57
  • The `TestLogger` behaves similar to a mock, so I'd argue it will achieve the desired outcome of the test, even if it isn't using a Spock mock. – Leonard Brünings Jun 04 '22 at 13:55
  • Oh OK, I see, it is necessary to declare the test logger as an implementation for SLF4J, i.e. basically the approach is not unlike what I suggested in my comments, i.e. creating a special configuration for SLF4j, using a mock appender and the desired log level. Previously, I just glanced at the examples, but not at the main page with config hints. My bad. This tool is of course more powerful than my approach, but OTOH it requires an extra dependency and maybe excludes for the normally used logger implementation for test scope. Cool tool, though. Sorry for the noise. – kriegaex Jun 04 '22 at 15:52