Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancment - Hamcrest matchers #3

Open
philipa opened this issue Jan 21, 2014 · 2 comments
Open

Enhancment - Hamcrest matchers #3

philipa opened this issue Jan 21, 2014 · 2 comments

Comments

@philipa
Copy link
Contributor

philipa commented Jan 21, 2014

I'm finding the following useful:

public static Matcher<LoggingEvent> debugContaining(String substring) {
    return formattedMessageMatches(Level.DEBUG, substring);
}

/// etc.

private static Matcher<LoggingEvent> formattedMessageMatches(
    final Level debug, final String substring) {

    return new BaseMatcher<LoggingEvent>() {

        @Override
        public boolean matches(Object item) {

            if (item instanceof LoggingEvent) {
                final LoggingEvent le = (LoggingEvent)item;

                return le.getLevel().equals(debug) &&
                    getFormattedMessage(le).indexOf(substring) >= 0;
            }

            return false;
        }

        @Override
        public void describeTo(Description description) {
            description
                .appendText("LoggingEvent with level ")
                .appendValue(debug)
                .appendText(" and a formatted message containing '")
                .appendText(substring)
                .appendText("'");
        }
    };
}


private static String getFormattedMessage(LoggingEvent event) {
    return MessageFormatter.arrayFormat(
        event.getMessage(), event.getArguments().toArray()).getMessage();
}

So I can say

    assertThat(logger.getAllLoggingEvents(),
        contains(
            debugContaining("first message"),
            debugContaining("the next message")));

Perhaps there should be a LoggingEventMatchers?

@quidryan
Copy link

The first thing I did was create my own matcher like this.

@e-g-hategan
Copy link

I've found this Hamcrest matcher useful (kotlin):

import org.hamcrest.Description
import org.hamcrest.Matcher
import org.hamcrest.TypeSafeMatcher
import org.slf4j.Marker
import uk.org.lidalia.slf4jext.Level
import uk.org.lidalia.slf4jtest.LoggingEvent

data class LoggingEventMatcher(
        private val level: Matcher<Level>? = null,
        private val mdc: Matcher<Map<String, String>>? = null,
        private val marker: Matcher<Marker>? = null,
        private val throwable: Matcher<Throwable>? = null,
        private val message: Matcher<String>? = null,
        private val arguments: Matcher<List<Any>>? = null
) : TypeSafeMatcher<LoggingEvent>() {

    override fun describeTo(description: Description?) {
        description?.appendText("a LoggingEvent")
        description?.appendText("[")

        appendDescriptionForMatchers(description, linkedMapOf(
                "level" to level,
                "mdc" to mdc,
                "marker" to marker,
                "throwable" to throwable,
                "message" to message,
                "arguments" to arguments
        ))

        description?.appendText("]")
    }

    private fun appendDescriptionForMatchers(description: Description?, matchers: Map<String, Matcher<*>?>) {
        var addSeparator = false
        for ((name, matcher) in matchers) {
            if (matcher != null) {
                if (addSeparator) {
                    description?.appendText(",")
                }
                description?.appendText(name)!!.appendText("=").appendDescriptionOf(matcher)
                addSeparator = true
            }
        }
    }

    override fun matchesSafely(item: LoggingEvent): Boolean {
        return (level == null || level.matches(item.level))
                && (mdc == null || mdc.matches(item.mdc))
                && (marker == null || marker.matches(item.marker.orNull()))
                && (throwable == null || throwable.matches(item.throwable.orNull()))
                && (message == null || message.matches(item.message))
                && (arguments == null || arguments.matches(item.arguments))
    }
}

then I can assert any part of the logging event like below (kotlin again)

    assertThat(logger.loggingEvents, hasItem(LoggingEventMatcher(level = equalTo(Level.ERROR), throwable = instanceOf(RuntimeException::class.java))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants