From 2161659bf6737b28f9fba76cde91a56cad47b9c1 Mon Sep 17 00:00:00 2001 From: Jeferson Perito Date: Fri, 22 Mar 2019 11:19:43 -0300 Subject: [PATCH] just improvements (#419) * Improving code quality and separation of concerns between handler and config. * unnecessary files removed --- audit/pom.xml | 10 ++ .../java/com/networknt/audit/AuditConfig.java | 121 +++++++++++++ .../com/networknt/audit/AuditHandler.java | 123 +++++-------- .../com/networknt/audit/AuditConfigTest.java | 144 ++++++++++++++++ .../com/networknt/audit/AuditHandlerTest.java | 161 ++++++++++++++++-- .../org.mockito.plugins.MockMaker | 1 + body/pom.xml | 5 + pom.xml | 13 ++ 8 files changed, 485 insertions(+), 93 deletions(-) create mode 100644 audit/src/main/java/com/networknt/audit/AuditConfig.java create mode 100644 audit/src/test/java/com/networknt/audit/AuditConfigTest.java create mode 100644 audit/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker diff --git a/audit/pom.xml b/audit/pom.xml index 59a4875410..fe9a5517f1 100644 --- a/audit/pom.xml +++ b/audit/pom.xml @@ -101,6 +101,16 @@ com.networknt mask + + org.powermock + powermock-api-mockito2 + test + + + org.powermock + powermock-module-junit4 + test + diff --git a/audit/src/main/java/com/networknt/audit/AuditConfig.java b/audit/src/main/java/com/networknt/audit/AuditConfig.java new file mode 100644 index 0000000000..17a213f9f8 --- /dev/null +++ b/audit/src/main/java/com/networknt/audit/AuditConfig.java @@ -0,0 +1,121 @@ +package com.networknt.audit; + +import com.networknt.config.Config; +import com.networknt.utility.Constants; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +class AuditConfig { + + private static final String HEADERS = "headers"; + private static final String AUDIT = "audit"; + private static final String STATUS_CODE = "statusCode"; + private static final String RESPONSE_TIME = "responseTime"; + private static final String AUDIT_ON_ERROR = "auditOnError"; + private static final String IS_LOG_LEVEL_ERROR = "logLevelIsError"; + private static final String IS_MASK_ENABLED = "mask"; + private final Map mappedConfig; + static final String CONFIG_NAME = "audit"; + private List headerList; + private List auditList; + + private Config config; + // A customized logger appender defined in default logback.xml + private Consumer auditFunc; + private boolean statusCode; + private boolean responseTime; + private boolean auditOnError; + private boolean isMaskEnabled; + + private AuditConfig() { + config = Config.getInstance(); + mappedConfig = config.getJsonMapConfigNoCache(CONFIG_NAME); + + setLists(); + setLogLevel(); + setConfigData(); + } + + static AuditConfig load() { + return new AuditConfig(); + } + + List getHeaderList() { + return headerList; + } + + List getAuditList() { + return auditList; + } + + Consumer getAuditFunc() { + return auditFunc; + } + + boolean isAuditOnError() { + return auditOnError; + } + + boolean isMaskEnabled() { + return isMaskEnabled; + } + + boolean isResponseTime() { + return responseTime; + } + + boolean isStatusCode() { + return statusCode; + } + + Map getMappedConfig() { + return mappedConfig; + } + + boolean hasHeaderList() { + return getHeaderList() != null && getHeaderList().size() > 0; + } + + boolean hasAuditList() { + return getAuditList() != null && getAuditList().size() > 0; + } + + Config getConfig() { + return config; + } + + private void setLogLevel() { + Object object = getMappedConfig().get(IS_LOG_LEVEL_ERROR); + auditFunc = (object != null && (Boolean) object) ? + LoggerFactory.getLogger(Constants.AUDIT_LOGGER)::error : LoggerFactory.getLogger(Constants.AUDIT_LOGGER)::info; + } + + private void setLists() { + headerList = (List) getMappedConfig().get(HEADERS); + auditList = (List) getMappedConfig().get(AUDIT); + } + + private void setConfigData() { + Object object = getMappedConfig().get(STATUS_CODE); + if(object != null && (Boolean) object) { + statusCode = true; + } + object = getMappedConfig().get(RESPONSE_TIME); + if(object != null && (Boolean) object) { + responseTime = true; + } + + // audit on error response flag + object = getMappedConfig().get(AUDIT_ON_ERROR); + if(object != null && (Boolean) object) { + auditOnError = true; + } + object = getMappedConfig().get(IS_MASK_ENABLED); + if(object != null && (Boolean) object) { + isMaskEnabled = true; + } + } +} diff --git a/audit/src/main/java/com/networknt/audit/AuditHandler.java b/audit/src/main/java/com/networknt/audit/AuditHandler.java index 990cd4c6ec..d50949df7d 100644 --- a/audit/src/main/java/com/networknt/audit/AuditHandler.java +++ b/audit/src/main/java/com/networknt/audit/AuditHandler.java @@ -21,7 +21,6 @@ import com.networknt.handler.Handler; import com.networknt.handler.MiddlewareHandler; import com.networknt.mask.Mask; -import com.networknt.utility.Constants; import com.networknt.utility.ModuleRegistry; import io.undertow.Handlers; import io.undertow.server.HttpHandler; @@ -31,9 +30,7 @@ import org.slf4j.LoggerFactory; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; -import java.util.function.Consumer; /** * This is a simple audit handler that dump most important info per request basis. The following @@ -71,105 +68,50 @@ */ public class AuditHandler implements MiddlewareHandler { static final Logger logger = LoggerFactory.getLogger(AuditHandler.class); - public static final String CONFIG_NAME = "audit"; public static final String ENABLED = "enabled"; - static final String HEADERS = "headers"; - static final String AUDIT = "audit"; static final String STATUS_CODE = "statusCode"; static final String RESPONSE_TIME = "responseTime"; static final String TIMESTAMP = "timestamp"; - static final String AUDIT_ON_ERROR = "auditOnError"; - static final String IS_LOG_LEVEL_ERROR = "logLevelIsError"; - static final String IS_MASK_ENABLED = "mask"; static final String MASK_KEY = "audit"; - public static final Map config; - private static final List headerList; - private static final List auditList; + private AuditConfig auditConfig; - private static boolean statusCode = false; - private static boolean responseTime = false; - private static boolean auditOnError = false; - private static boolean isMaskEnabled = false; - - // A customized logger appender defined in default logback.xml - static Consumer auditFunc = LoggerFactory.getLogger(Constants.AUDIT_LOGGER)::info; // The key to the audit info attachment in exchange. Allow other handlers to set values. public static final AttachmentKey AUDIT_INFO = AttachmentKey.create(Map.class); private volatile HttpHandler next; - static { - config = Config.getInstance().getJsonMapConfigNoCache(CONFIG_NAME); - headerList = (List)config.get(HEADERS); - auditList = (List)config.get(AUDIT); - Object object = config.get(STATUS_CODE); - if(object != null && (Boolean) object) { - statusCode = true; - } - object = config.get(RESPONSE_TIME); - if(object != null && (Boolean) object) { - responseTime = true; - } - - // audit on error response flag - object = config.get(AUDIT_ON_ERROR); - if(object != null && (Boolean) object) { - auditOnError = true; - } - - // set the log level - object = config.get(IS_LOG_LEVEL_ERROR); - auditFunc = (object != null && (Boolean) object) ? - LoggerFactory.getLogger(Constants.AUDIT_LOGGER)::error : LoggerFactory.getLogger(Constants.AUDIT_LOGGER)::info; - - // use mask flag - object = config.get(IS_MASK_ENABLED); - if(object != null && (Boolean) object) { - isMaskEnabled = true; - } + public AuditHandler() { + if(logger.isInfoEnabled()) logger.info("AuditHandler is loaded."); + auditConfig = AuditConfig.load(); } - public AuditHandler() { if(logger.isInfoEnabled()) logger.info("AuditHandler is loaded."); } - @Override public void handleRequest(final HttpServerExchange exchange) throws Exception { Map auditInfo = exchange.getAttachment(AuditHandler.AUDIT_INFO); Map auditMap = new LinkedHashMap<>(); final long start = System.currentTimeMillis(); auditMap.put(TIMESTAMP, System.currentTimeMillis()); + // dump audit info fields according to config - if(auditInfo != null) { - if(auditList != null && auditList.size() > 0) { - for(String name: auditList) { - Object value = auditInfo.get(name); - if(isMaskEnabled && value instanceof String) { - auditMap.put(name, Mask.maskRegex((String) value, MASK_KEY, name)); - } else { - auditMap.put(name, value); - } - } - } + boolean needAuditData = auditInfo != null && auditConfig.hasAuditList(); + if(needAuditData) { + auditFields(auditInfo, auditMap); } + // dump headers field according to config - if(headerList != null && headerList.size() > 0) { - for(String name: headerList) { - String value = exchange.getRequestHeaders().getFirst(name); - if (isMaskEnabled) { - auditMap.put(name, Mask.maskRegex(value, "requestHeader", name)); - } else { - auditMap.put(name, value); - } - } + if(auditConfig.hasHeaderList()) { + auditHeader(exchange, auditMap); } - if(statusCode || responseTime) { + + if(auditConfig.isStatusCode() || auditConfig.isResponseTime()) { exchange.addExchangeCompleteListener((exchange1, nextListener) -> { - if (AuditHandler.statusCode) { + if (auditConfig.isStatusCode()) { auditMap.put(STATUS_CODE, exchange1.getStatusCode()); } - if (responseTime) { + if (auditConfig.isResponseTime()) { auditMap.put(RESPONSE_TIME, System.currentTimeMillis() - start); } @@ -177,8 +119,8 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception { // according to the config //Map auditInfo1 = exchange.getAttachment(AuditHandler.AUDIT_INFO); if(auditInfo != null) { - if(auditList != null && auditList.size() > 0) { - for(String name: auditList) { + if(auditConfig.getAuditList() != null && auditConfig.getAuditList().size() > 0) { + for(String name: auditConfig.getAuditList()) { auditMap.putIfAbsent(name, auditInfo.get(name)); } } @@ -186,11 +128,11 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception { try { // audit entries only is it is an error, if auditOnError flag is set - if(auditOnError) { + if(auditConfig.isAuditOnError()) { if (exchange1.getStatusCode() >= 400) - auditFunc.accept(Config.getInstance().getMapper().writeValueAsString(auditMap)); + auditConfig.getAuditFunc().accept(Config.getInstance().getMapper().writeValueAsString(auditMap)); } else { - auditFunc.accept(Config.getInstance().getMapper().writeValueAsString(auditMap)); + auditConfig.getAuditFunc().accept(Config.getInstance().getMapper().writeValueAsString(auditMap)); } } catch (JsonProcessingException e) { throw new RuntimeException(e); @@ -199,11 +141,30 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception { nextListener.proceed(); }); } else { - auditFunc.accept(Config.getInstance().getMapper().writeValueAsString(auditMap)); + auditConfig.getAuditFunc().accept(auditConfig.getConfig().getMapper().writeValueAsString(auditMap)); + } + next(exchange); + } + + private void auditHeader(HttpServerExchange exchange, Map auditMap) { + for(String name: auditConfig.getHeaderList()) { + String value = exchange.getRequestHeaders().getFirst(name); + auditMap.put(name, auditConfig.isMaskEnabled() ? Mask.maskRegex(value, "requestHeader", name) : value); } + } + + protected void next(HttpServerExchange exchange) throws Exception { Handler.next(exchange, next); } + private void auditFields(Map auditInfo, Map auditMap) { + for(String name: auditConfig.getAuditList()) { + Object value = auditInfo.get(name); + boolean needApplyMask = auditConfig.isMaskEnabled() && value instanceof String; + auditMap.put(name, needApplyMask ? Mask.maskRegex((String) value, MASK_KEY, name) : value); + } + } + @Override public HttpHandler getNext() { return next; @@ -218,12 +179,12 @@ public MiddlewareHandler setNext(final HttpHandler next) { @Override public boolean isEnabled() { - Object object = config.get(ENABLED); + Object object = auditConfig.getMappedConfig().get(ENABLED); return object != null && (Boolean) object; } @Override public void register() { - ModuleRegistry.registerModule(AuditHandler.class.getName(), config, null); + ModuleRegistry.registerModule(AuditHandler.class.getName(), auditConfig.getMappedConfig(), null); } } diff --git a/audit/src/test/java/com/networknt/audit/AuditConfigTest.java b/audit/src/test/java/com/networknt/audit/AuditConfigTest.java new file mode 100644 index 0000000000..77f02c0dcb --- /dev/null +++ b/audit/src/test/java/com/networknt/audit/AuditConfigTest.java @@ -0,0 +1,144 @@ +package com.networknt.audit; + +import com.networknt.config.Config; +import com.networknt.utility.Constants; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import static com.networknt.audit.AuditConfig.CONFIG_NAME; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(fullyQualifiedNames = {"com.networknt.config.Config", "org.slf4j.LoggerFactory"}) +public class AuditConfigTest { + + @Before + public void setUp() { + PowerMockito.mockStatic(Config.class); + PowerMockito.mockStatic(LoggerFactory.class); + } + + @Test + public void shouldLoadEmptyConfig() { + Logger logger = Mockito.mock(Logger.class); + Mockito.when(LoggerFactory.getLogger(Constants.AUDIT_LOGGER)).thenReturn(logger); + + Config config = Mockito.mock(Config.class); + Mockito.when(config.getJsonMapConfigNoCache(CONFIG_NAME)).thenReturn(new HashMap<>()); + + Mockito.when(Config.getInstance()).thenReturn(config); + AuditConfig configHandler = AuditConfig.load(); + + Assert.assertFalse(configHandler.hasAuditList()); + Assert.assertFalse(configHandler.hasHeaderList()); + Assert.assertNotNull(configHandler.getAuditFunc()); + Assert.assertNull(configHandler.getAuditList()); + Assert.assertNull(configHandler.getHeaderList()); + Assert.assertFalse(configHandler.isStatusCode()); + Assert.assertFalse(configHandler.isResponseTime()); + Assert.assertFalse(configHandler.isAuditOnError()); + Assert.assertFalse(configHandler.isMaskEnabled()); + } + + @Test + public void shouldLoadFalseValuesConfig() { + HashMap configMap = createMapValues(false); + + Logger logger = Mockito.mock(Logger.class); + Mockito.when(LoggerFactory.getLogger(Constants.AUDIT_LOGGER)).thenReturn(logger); + + Config config = Mockito.mock(Config.class); + Mockito.when(config.getJsonMapConfigNoCache(CONFIG_NAME)).thenReturn(configMap); + Mockito.when(Config.getInstance()).thenReturn(config); + + AuditConfig configHandler = AuditConfig.load(); + + Assert.assertFalse(configHandler.hasAuditList()); + Assert.assertFalse(configHandler.hasHeaderList()); + Assert.assertNotNull(configHandler.getAuditFunc()); + Assert.assertTrue(configHandler.getAuditList().isEmpty()); + Assert.assertTrue(configHandler.getHeaderList().isEmpty()); + Assert.assertFalse(configHandler.isStatusCode()); + Assert.assertFalse(configHandler.isResponseTime()); + Assert.assertFalse(configHandler.isAuditOnError()); + Assert.assertFalse(configHandler.isMaskEnabled()); + + configHandler.getAuditFunc().accept(""); + Mockito.verify(logger, Mockito.never()).error(Mockito.anyString()); + Mockito.verify(logger).info(Mockito.anyString()); + } + + + @Test + public void shouldLoadTrueValuesConfig() { + HashMap configMap = createMapValues(true); + + Logger logger = Mockito.mock(Logger.class); + Mockito.when(LoggerFactory.getLogger(Constants.AUDIT_LOGGER)).thenReturn(logger); + + Config config = Mockito.mock(Config.class); + Mockito.when(config.getJsonMapConfigNoCache(CONFIG_NAME)).thenReturn(configMap); + Mockito.when(Config.getInstance()).thenReturn(config); + + AuditConfig configHandler = AuditConfig.load(); + + Assert.assertFalse(configHandler.hasAuditList()); + Assert.assertFalse(configHandler.hasHeaderList()); + Assert.assertNotNull(configHandler.getAuditFunc()); + Assert.assertTrue(configHandler.getAuditList().isEmpty()); + Assert.assertTrue(configHandler.getHeaderList().isEmpty()); + Assert.assertTrue(configHandler.isStatusCode()); + Assert.assertTrue(configHandler.isResponseTime()); + Assert.assertTrue(configHandler.isAuditOnError()); + Assert.assertTrue(configHandler.isMaskEnabled()); + + configHandler.getAuditFunc().accept(""); + Mockito.verify(logger).error(Mockito.anyString()); + Mockito.verify(logger, Mockito.never()).info(Mockito.anyString()); + } + + @Test + public void shouldGetListOfStringsForHeadersAndAuditConfig() { + List headers = Arrays.asList("header1", "header2"); + List audit = Arrays.asList("audit1", "audit2"); + + HashMap configMap = new HashMap<>(); + configMap.put("headers", headers); + configMap.put("audit", audit); + + Logger logger = Mockito.mock(Logger.class); + Mockito.when(LoggerFactory.getLogger(Constants.AUDIT_LOGGER)).thenReturn(logger); + + Config config = Mockito.mock(Config.class); + Mockito.when(config.getJsonMapConfigNoCache(CONFIG_NAME)).thenReturn(configMap); + Mockito.when(Config.getInstance()).thenReturn(config); + + AuditConfig configHandler = AuditConfig.load(); + + Assert.assertEquals(headers, configHandler.getHeaderList()); + Assert.assertEquals(audit, configHandler.getAuditList()); + } + + private HashMap createMapValues(boolean typeOfValue) { + HashMap configMap = new HashMap<>(); + configMap.put("headers", Arrays.asList()); + configMap.put("audit", Arrays.asList()); + configMap.put("statusCode", typeOfValue); + configMap.put("responseTime", typeOfValue); + configMap.put("auditOnError", typeOfValue); + configMap.put("logLevelIsError", typeOfValue); + configMap.put("mask", typeOfValue); + return configMap; + } +} diff --git a/audit/src/test/java/com/networknt/audit/AuditHandlerTest.java b/audit/src/test/java/com/networknt/audit/AuditHandlerTest.java index 91081f81ed..a7ae70bd7b 100644 --- a/audit/src/test/java/com/networknt/audit/AuditHandlerTest.java +++ b/audit/src/test/java/com/networknt/audit/AuditHandlerTest.java @@ -19,10 +19,13 @@ import ch.qos.logback.classic.Level; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Appender; +import com.fasterxml.jackson.databind.ObjectMapper; import com.networknt.client.Http2Client; +import com.networknt.config.Config; import com.networknt.config.JsonMapper; import com.networknt.correlation.CorrelationHandler; import com.networknt.exception.ClientException; +import com.networknt.handler.Handler; import com.networknt.httpstring.HttpStringConstants; import com.networknt.utility.Constants; import io.undertow.Handlers; @@ -31,20 +34,19 @@ import io.undertow.client.ClientRequest; import io.undertow.client.ClientResponse; import io.undertow.server.HttpHandler; +import io.undertow.server.HttpServerExchange; import io.undertow.server.RoutingHandler; +import io.undertow.util.AttachmentKey; +import io.undertow.util.HeaderMap; import io.undertow.util.Headers; import io.undertow.util.Methods; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.*; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.*; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xnio.IoUtils; @@ -56,6 +58,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -63,9 +66,11 @@ /** * Created by steve on 01/09/16. */ -@RunWith(MockitoJUnitRunner.class) +@RunWith(PowerMockRunner.class) +@PrepareForTest({AuditConfig.class, LoggerFactory.class}) +@PowerMockIgnore({"javax.xml.*", "org.xml.sax.*", "org.apache.log4j.*"}) public class AuditHandlerTest { - static final Logger logger = LoggerFactory.getLogger(AuditHandlerTest.class); + static Logger logger = LoggerFactory.getLogger(AuditHandlerTest.class); static Undertow server = null; @@ -231,4 +236,136 @@ public void run() { } verifyAuditLog(null); } + + @Test + public void shouldAddListenerIfIsStatusCodeAndIsResponseTimeAreTrue() throws Exception { + PowerMockito.mockStatic(AuditConfig.class); + + AuditConfig configHandler = Mockito.mock(AuditConfig.class); + Mockito.when(configHandler.isResponseTime()).thenReturn(true); + Mockito.when(configHandler.isStatusCode()).thenReturn(true); + + Mockito.when(AuditConfig.load()).thenReturn(configHandler); + + HeaderMap headerMap = Mockito.spy(new HeaderMap()); + HttpServerExchange httpServerExchange = Mockito.mock(HttpServerExchange.class); + Mockito.when(httpServerExchange.getRequestHeaders()).thenReturn(headerMap); + + AuditHandler auditHandler = Mockito.spy(new AuditHandler()); + Mockito.doNothing().when(auditHandler).next(Mockito.any()); + + Handler.init(); + + auditHandler.handleRequest(httpServerExchange); + Mockito.verify(httpServerExchange).addExchangeCompleteListener(Mockito.any()); + } + + @Test + public void shouldAddListenerIfIsStatusCodeIsFalseAndIsResponseTimeIsTrue() throws Exception { + PowerMockito.mockStatic(AuditConfig.class); + + AuditConfig configHandler = Mockito.mock(AuditConfig.class); + Mockito.when(configHandler.isResponseTime()).thenReturn(true); + Mockito.when(configHandler.isStatusCode()).thenReturn(false); + + Mockito.when(AuditConfig.load()).thenReturn(configHandler); + + HeaderMap headerMap = Mockito.spy(new HeaderMap()); + HttpServerExchange httpServerExchange = Mockito.mock(HttpServerExchange.class); + Mockito.when(httpServerExchange.getRequestHeaders()).thenReturn(headerMap); + + AuditHandler auditHandler = Mockito.spy(new AuditHandler()); + Mockito.doNothing().when(auditHandler).next(Mockito.any()); + + Handler.init(); + + auditHandler.handleRequest(httpServerExchange); + Mockito.verify(httpServerExchange).addExchangeCompleteListener(Mockito.any()); + } + + @Test + public void shouldAddListenerIfIsStatusCodeIsTrueAndIsResponseTimeIsFalse() throws Exception { + PowerMockito.mockStatic(AuditConfig.class); + + AuditConfig configHandler = Mockito.mock(AuditConfig.class); + Mockito.when(configHandler.isResponseTime()).thenReturn(false); + Mockito.when(configHandler.isStatusCode()).thenReturn(true); + + Mockito.when(AuditConfig.load()).thenReturn(configHandler); + + HeaderMap headerMap = Mockito.spy(new HeaderMap()); + HttpServerExchange httpServerExchange = Mockito.mock(HttpServerExchange.class); + Mockito.when(httpServerExchange.getRequestHeaders()).thenReturn(headerMap); + + AuditHandler auditHandler = Mockito.spy(new AuditHandler()); + Mockito.doNothing().when(auditHandler).next(Mockito.any()); + + Handler.init(); + + auditHandler.handleRequest(httpServerExchange); + Mockito.verify(httpServerExchange).addExchangeCompleteListener(Mockito.any()); + } + + @Test + public void shouldNotAddListenerIfStatusCodeAndResponseTimeAreFalse() throws Exception { + PowerMockito.mockStatic(AuditConfig.class); + Consumer auditFunc= (Consumer) Mockito.spy(Consumer.class); + ObjectMapper objectMapper = Mockito.mock(ObjectMapper.class); + + Config config = Mockito.mock(Config.class); + Mockito.when(config.getMapper()).thenReturn(objectMapper); + + AuditConfig configHandler = Mockito.mock(AuditConfig.class); + Mockito.when(configHandler.isResponseTime()).thenReturn(false); + Mockito.when(configHandler.isStatusCode()).thenReturn(false); + Mockito.when(configHandler.getAuditFunc()).thenReturn(auditFunc); + Mockito.when(configHandler.getConfig()).thenReturn(config); + + Mockito.when(AuditConfig.load()).thenReturn(configHandler); + + HttpServerExchange httpServerExchange = Mockito.mock(HttpServerExchange.class); + + AuditHandler auditHandler = Mockito.spy(new AuditHandler()); + Mockito.doNothing().when(auditHandler).next(Mockito.any()); + + Handler.init(); + + auditHandler.handleRequest(httpServerExchange); + Mockito.verify(httpServerExchange, Mockito.never()).addExchangeCompleteListener(Mockito.any()); + Mockito.verify(auditFunc).accept(Mockito.any()); + Mockito.verify(objectMapper).writeValueAsString(Mockito.any()); + } + + private class ArgumentMatcherAuditInfo implements ArgumentMatcher> { + + @Override + public boolean matches(AttachmentKey attachmentKey) { + if (attachmentKey == null) { + return false; + } + return attachmentKey.toString().equals("io.undertow.util.SimpleAttachmentKey"); + } + } + + private class ArgumentMatcherChainId implements ArgumentMatcher> { + + @Override + public boolean matches(AttachmentKey attachmentKey) { + if (attachmentKey == null) { + return false; + } + return attachmentKey.toString().equals("io.undertow.util.SimpleAttachmentKey"); + } + } + + private class ArgumentMatcherChainSeq implements ArgumentMatcher> { + + @Override + public boolean matches(AttachmentKey attachmentKey) { + if (attachmentKey == null) { + return false; + } + return attachmentKey.toString().equals("io.undertow.util.SimpleAttachmentKey"); + } + } } diff --git a/audit/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/audit/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000000..ca6ee9cea8 --- /dev/null +++ b/audit/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file diff --git a/body/pom.xml b/body/pom.xml index 00f3d8e189..07c6a854d2 100644 --- a/body/pom.xml +++ b/body/pom.xml @@ -82,6 +82,11 @@ client test + + org.mockito + mockito-core + test + diff --git a/pom.xml b/pom.xml index f89d05de7d..a6287f1317 100644 --- a/pom.xml +++ b/pom.xml @@ -75,6 +75,7 @@ 1.2.3 4.12 2.10.0 + 2.0.0 2.0.16.Final 1.0.34 1.3 @@ -531,6 +532,18 @@ ${version.mockito} test + + org.powermock + powermock-api-mockito2 + ${version.powermock} + test + + + org.powermock + powermock-module-junit4 + ${version.powermock} + test + org.hamcrest hamcrest-library