Integration tests
Integration tests are checking if your microservices are communicating properly and they are doing their job fine. That means during this type of testing your code is communicating with microservices running on JLupin Next Server. It is including using built-in load balancers and all other JLupin Next Server features. This is making integration tests similar as possible to system running on production. Test class will call service running on JLupin Next Server as an outer client.
Example integration test with implementation is shown below:
example-b
Service interface:
package com.example.service.interfaces;
public interface BService {
String callB(String input);
}
Service implementation:
package com.example.service.impl;
import com.example.service.interfaces.BService;
import org.springframework.stereotype.Service;
@Service(value = "bService")
public class BServiceImpl implements BService {
@Override
public String callB(String input) {
return "[called B]" + input;
}
}
Spring configuration file:
package com.example.configuration;
import com.jlupin.impl.client.util.JLupinClientUtil;
import com.jlupin.interfaces.client.delegator.JLupinDelegator;
import com.jlupin.interfaces.common.enums.PortType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.List;
@Configuration
@ComponentScan("com.example")
public class ExampleBSpringConfiguration {
@Bean
public JLupinDelegator getJLupinDelegator() {
return JLupinClientUtil.generateInnerMicroserviceLoadBalancerDelegator(PortType.JLRMC);
}
@Bean(name = "jLupinRegularExpressionToRemotelyEnabled")
public List getRemotelyBeanList() {
List<String> list = new ArrayList<>();
list.add("bService");
// list.add("<REMOTE_SERVICE_NAME>");
return list;
}
}
JLupin Next Server configuration file:
package com.example.configuration;
import com.jlupin.impl.container.application.spring.JLupinAbstractSpringApplicationContainer;
import com.jlupin.interfaces.configuration.microservice.container.application.JLupinAbstractApplicationContainerProducer;
import com.jlupin.interfaces.container.application.JLupinApplicationContainer;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class ExampleBJLupinConfiguration extends JLupinAbstractApplicationContainerProducer {
@Override
public JLupinApplicationContainer produceJLupinApplicationContainer() {
return new JLupinAbstractSpringApplicationContainer() {
@Override
public AbstractApplicationContext getAbstractApplicationContext() {
return new AnnotationConfigApplicationContext(ExampleBSpringConfiguration.class);
}
};
}
}
Compile all above classes and pack them into jar archive. Then create example-b
directory somewhere. This will be the name of the microservice. Put inside newly created jar archive and microservice configuration file. Example configuration is shown below. If you want to know more about configuration microservices please folow here.
Microservice configuration.yml
file:
SERVERS:
JLRMC: #JLupin Remote Method Calls Fast Protocol
readTimeout: 480000
isWaitForFinishExecuteAllRequests: true
waitToShutdownThreadsOnStop: 60000
backlog: 0
receiveBufferSize: 0
isReuseAddress: false
threadPoolSize: 128
isLogPeriodicOnDebug: true
isDestroyThreadOnTimeout: false
threadExecutingTimeOut: 240000
TRANSMISSION:
readTimeout: 480000
isWaitForFinishExecuteAllRequests: false
waitToShutdownThreadsOnStop: 60000
backlog: 0
receiveBufferSize: 0
isReuseAddress: false
threadPoolSize: 8
isLogPeriodicOnDebug: true
isDestroyThreadOnTimeout: false
threadExecutingTimeOut: 3600000
QUEUE:
readTimeout: 480000
isWaitForFinishExecuteAllRequests: true
waitToShutdownThreadsOnStop: 60000
backlog: 0
receiveBufferSize: 0
isReuseAddress: false
threadPoolSize: 128
isLogPeriodicOnDebug: true
isDestroyThreadOnTimeout: false
threadExecutingTimeOut: 240000
PROPERTIES:
#jvmOptions1: '-Xms128M -Xmx256M -agentlib:jdwp=transport=dt_socket,address=12998,server=y,suspend=n'
jvmOptions1: '-Xms128M -Xmx256M' #jvmOptions_2 - default the same as jvmOptions_1
#jvmOptions2: '-Xms128M -Xmx256M'
switchDelayTime: 0
connectionSocketTimeoutInMillis: 1000
readTimeoutInMillis: 30000
expectedCheckResponseTimeInMillis: 2000
isKeepAlive: false
isOOBInline: false
isTcpNoDelay: false
isReuseAddress: false
sendBufferSize: 0
receiveBufferSize: 0
soLinger: 0
trafficClass: 0
#javaExecutablePath: 'c:\\jvm\\bin\\java.exe'
#additionalClassPath: 'c:\\temp\\*'
isStartOnMainServerInitialize: true
priorityStartOnMainServerInitialize: 4
waitForProcessInitResponseTimeInMillis: 90000
waitForProcessStartResponseTimeInMillis: 90000
waitForProcessDestroyResponseTimeInMillis: 30000
isAllFilesToJVMAppClassLoader: false
isArchiveOnStart: false
startLogMode: INFO
isInitErrorCauseWithNetworkInformation: true
checkAvailableScript: 'function isAvailable(checkResponseTimeInMillis, jrmcActiveThreads, jrmcMaxThreads,
queueActiveThreads, queueMaxThreads, servletActiveThreads, servletMaxThreads,
jvmMaxMemoryInBytes, jvmTotalMemoryInBytes, jvmFreeMemoryInBytes,
jvmProcessCpuLoadInPercentage, userAvailableFlag) {
var isAvailableByUser = Boolean(userAvailableFlag);
if(checkResponseTimeInMillis > 20000 || !isAvailableByUser) {
return false;
}
return true;
}'
APPLICATION:
applicationContainerProducerClassName: 'com.example.configuration.ExampleBJLupinConfiguration'
INITIALIZING_LOGGER:
#directoryPath: '/logs/server'
#fileName: 'file_name'
fileExtension: 'log'
fileSizeInMB: 20
maxFiles: 10
MEMORY_ERRORS:
isRestartOnError: true
howManyTimes: 4
percentageGrowth: 15
isHeapDump: true
THREAD_POOLS:
THREAD_POOL_1:
size: 8
waitingTimeForTasksCompletionInMillis: 10000
#THREAD_POOL_2:
# size: 8
# waitingTimeForTasksCompletionInMillis: 10000
You can also include here configuration file for Log4j2 (log4j2.xml
):
<?xml version="1.0" encoding="UTF-8"?>
<!-- ===================================================================== -->
<!-- -->
<!-- Log4j2 Configuration -->
<!-- -->
<!-- ===================================================================== -->
<!--
| For more configuration information and examples see the Apache Log4j2
| website: https://logging.apache.org/log4j/2.x/index.html
-->
<Configuration status="WARN">
<!-- Extract log directory and file name into variables -->
<Properties>
<Property name="logDirectory">../logs/microservice/example-b</Property>
<Property name="logFileName">microservice</Property>
</Properties>
<Appenders>
<!-- RollingFileAppender configured to role every day -->
<RollingFile name="FILE">
<FileName>${logDirectory}/${logFileName}.log</FileName>
<FilePattern>${logDirectory}/${logFileName}.%d{yyyy-MM-dd}.log</FilePattern>
<!-- Compress log files to gzip -->
<!-- More configuration https://logging.apache.org/log4j/2.x/manual/appenders.html#DefaultRolloverStrategy -->
<!-- <FilePattern>${logDirectory}/${logFileName}.%d{yyyy-MM-dd}.log.gz</FilePattern> -->
<!-- Do not truncate file -->
<Append>true</Append>
<!-- The default pattern: Date Priority [Category] (Thread) Message\n -->
<PatternLayout pattern="%d %-5p [%c] (%t) %m%n" />
<Policies>
<!-- Rollover every microservice start - very useful for debugging -->
<!-- <OnStartupTriggeringPolicy /> -->
<!-- Rollover at the top of each day -->
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
<!-- Rollover if file size is greater than 200 MB -->
<!-- <SizeBasedTriggeringPolicy size="200 MB"/> -->
</Policies>
<!-- Keep last 10 log files -->
<!-- More configuration https://logging.apache.org/log4j/2.x/manual/appenders.html#DefaultRolloverStrategy -->
<!-- <DefaultRolloverStrategy max="10" /> -->
</RollingFile>
<!-- AsyncAppender for high performance -->
<Async name="ASYNC_FILE">
<BufferSize>1000</BufferSize>
<AppenderRef ref="FILE" />
</Async>
</Appenders>
<Loggers>
<!-- Setup for root logger with AsyncAppender -->
<Root level="info">
<AppenderRef ref="ASYNC_FILE" />
</Root>
</Loggers>
</Configuration>
Now pack your example-b
directory into zip file example-b.zip
(inside zip at top level there should be visible example-b
directory), start JLupin Next Server (start.sh/start.cmd
) and run control (control.sh/control.cmd
). Copy created zip file example-b.zip
into upload
directory. Then from control window run command microservice upload example-b.zip
. Your microservice will be uploaded to server and started. You can significantly speed up this process with our JCS JLupin Next Server Maven Plugin and also with our JCS JLupin Next Server IntelliJ Plugin.
example-a
Service interface:
package com.example.service.interfaces;
public interface AService {
String callA(String input);
}
Service implementation:
package com.example.service.impl;
import com.example.service.interfaces.AService;
import com.example.service.interfaces.BService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service(value = "aService")
public class AServiceImpl implements AService {
@Autowired
private BService bService;
@Override
public String callA(String input) {
return "[called A]" + bService.callB(input);
}
}
Spring configuration file:
package com.example.configuration;
import com.example.service.interfaces.BService;
import com.jlupin.impl.client.util.JLupinClientUtil;
import com.jlupin.interfaces.client.delegator.JLupinDelegator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.List;
@Configuration
@ComponentScan("com.example")
public class ExampleASpringConfiguration {
@Bean
public JLupinDelegator getJLupinDelegator() {
return JLupinClientUtil.generateInnerMicroserviceLoadBalancerDelegator(PortType.JLRMC);
}
@Bean(name = "bService")
public BService getExampleService() {
return JLupinClientUtil.generateRemote(getJLupinDelegator(), "example-b", "bService", BService.class);
}
@Bean(name = "jLupinRegularExpressionToRemotelyEnabled")
public List getRemotelyBeanList() {
List<String> list = new ArrayList<>();
list.add("aService");
// list.add("<REMOTE_SERVICE_NAME>");
return list;
}
}
JLupin Next Server configuration file:
package com.example.configuration;
import com.jlupin.impl.container.application.spring.JLupinAbstractSpringApplicationContainer;
import com.jlupin.interfaces.configuration.microservice.container.application.JLupinAbstractApplicationContainerProducer;
import com.jlupin.interfaces.container.application.JLupinApplicationContainer;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class ExampleAJLupinConfiguration extends JLupinAbstractApplicationContainerProducer {
@Override
public JLupinApplicationContainer produceJLupinApplicationContainer() {
return new JLupinAbstractSpringApplicationContainer() {
@Override
public AbstractApplicationContext getAbstractApplicationContext() {
return new AnnotationConfigApplicationContext(ExampleASpringConfiguration.class);
}
};
}
}
Compile all above classes and pack them into jar archive. Then create example-a
directory somewhere. This will be the name of the microservice. Put inside newly created jar archive and microservice configuration file. Example configuration is shown below. If you want to know more about configuration microservices please folow here.
Microservice configuration.yml
file:
SERVERS:
JLRMC: #JLupin Remote Method Calls Fast Protocol
readTimeout: 480000
isWaitForFinishExecuteAllRequests: true
waitToShutdownThreadsOnStop: 60000
backlog: 0
receiveBufferSize: 0
isReuseAddress: false
threadPoolSize: 128
isLogPeriodicOnDebug: true
isDestroyThreadOnTimeout: false
threadExecutingTimeOut: 240000
TRANSMISSION:
readTimeout: 480000
isWaitForFinishExecuteAllRequests: false
waitToShutdownThreadsOnStop: 60000
backlog: 0
receiveBufferSize: 0
isReuseAddress: false
threadPoolSize: 8
isLogPeriodicOnDebug: true
isDestroyThreadOnTimeout: false
threadExecutingTimeOut: 3600000
QUEUE:
readTimeout: 480000
isWaitForFinishExecuteAllRequests: true
waitToShutdownThreadsOnStop: 60000
backlog: 0
receiveBufferSize: 0
isReuseAddress: false
threadPoolSize: 128
isLogPeriodicOnDebug: true
isDestroyThreadOnTimeout: false
threadExecutingTimeOut: 240000
PROPERTIES:
#jvmOptions1: '-Xms128M -Xmx256M -agentlib:jdwp=transport=dt_socket,address=12998,server=y,suspend=n'
jvmOptions1: '-Xms128M -Xmx256M' #jvmOptions_2 - default the same as jvmOptions_1
#jvmOptions2: '-Xms128M -Xmx256M'
switchDelayTime: 0
connectionSocketTimeoutInMillis: 1000
readTimeoutInMillis: 30000
expectedCheckResponseTimeInMillis: 2000
isKeepAlive: false
isOOBInline: false
isTcpNoDelay: false
isReuseAddress: false
sendBufferSize: 0
receiveBufferSize: 0
soLinger: 0
trafficClass: 0
#javaExecutablePath: 'c:\\jvm\\bin\\java.exe'
#additionalClassPath: 'c:\\temp\\*'
isStartOnMainServerInitialize: true
priorityStartOnMainServerInitialize: 4
waitForProcessInitResponseTimeInMillis: 90000
waitForProcessStartResponseTimeInMillis: 90000
waitForProcessDestroyResponseTimeInMillis: 30000
isAllFilesToJVMAppClassLoader: false
isArchiveOnStart: false
startLogMode: INFO
isInitErrorCauseWithNetworkInformation: true
checkAvailableScript: 'function isAvailable(checkResponseTimeInMillis, jrmcActiveThreads, jrmcMaxThreads,
queueActiveThreads, queueMaxThreads, servletActiveThreads, servletMaxThreads,
jvmMaxMemoryInBytes, jvmTotalMemoryInBytes, jvmFreeMemoryInBytes,
jvmProcessCpuLoadInPercentage, userAvailableFlag) {
var isAvailableByUser = Boolean(userAvailableFlag);
if(checkResponseTimeInMillis > 20000 || !isAvailableByUser) {
return false;
}
return true;
}'
APPLICATION:
applicationContainerProducerClassName: 'com.example.configuration.ExampleAJLupinConfiguration'
INITIALIZING_LOGGER:
#directoryPath: '/logs/server'
#fileName: 'file_name'
fileExtension: 'log'
fileSizeInMB: 20
maxFiles: 10
MEMORY_ERRORS:
isRestartOnError: true
howManyTimes: 4
percentageGrowth: 15
isHeapDump: true
THREAD_POOLS:
THREAD_POOL_1:
size: 8
waitingTimeForTasksCompletionInMillis: 10000
#THREAD_POOL_2:
# size: 8
# waitingTimeForTasksCompletionInMillis: 10000
You can also include here configuration file for Log4j (log4j.xml
):
<?xml version="1.0" encoding="UTF-8"?>
<!-- ===================================================================== -->
<!-- -->
<!-- Log4j2 Configuration -->
<!-- -->
<!-- ===================================================================== -->
<!--
| For more configuration information and examples see the Apache Log4j2
| website: https://logging.apache.org/log4j/2.x/index.html
-->
<Configuration status="WARN">
<!-- Extract log directory and file name into variables -->
<Properties>
<Property name="logDirectory">../logs/microservice/example-a</Property>
<Property name="logFileName">microservice</Property>
</Properties>
<Appenders>
<!-- RollingFileAppender configured to role every day -->
<RollingFile name="FILE">
<FileName>${logDirectory}/${logFileName}.log</FileName>
<FilePattern>${logDirectory}/${logFileName}.%d{yyyy-MM-dd}.log</FilePattern>
<!-- Compress log files to gzip -->
<!-- More configuration https://logging.apache.org/log4j/2.x/manual/appenders.html#DefaultRolloverStrategy -->
<!-- <FilePattern>${logDirectory}/${logFileName}.%d{yyyy-MM-dd}.log.gz</FilePattern> -->
<!-- Do not truncate file -->
<Append>true</Append>
<!-- The default pattern: Date Priority [Category] (Thread) Message\n -->
<PatternLayout pattern="%d %-5p [%c] (%t) %m%n" />
<Policies>
<!-- Rollover every microservice start - very useful for debugging -->
<!-- <OnStartupTriggeringPolicy /> -->
<!-- Rollover at the top of each day -->
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
<!-- Rollover if file size is greater than 200 MB -->
<!-- <SizeBasedTriggeringPolicy size="200 MB"/> -->
</Policies>
<!-- Keep last 10 log files -->
<!-- More configuration https://logging.apache.org/log4j/2.x/manual/appenders.html#DefaultRolloverStrategy -->
<!-- <DefaultRolloverStrategy max="10" /> -->
</RollingFile>
<!-- AsyncAppender for high performance -->
<Async name="ASYNC_FILE">
<BufferSize>1000</BufferSize>
<AppenderRef ref="FILE" />
</Async>
</Appenders>
<Loggers>
<!-- Setup for root logger with AsyncAppender -->
<Root level="info">
<AppenderRef ref="ASYNC_FILE" />
</Root>
</Loggers>
</Configuration>
Now pack your example-a
directory into zip file example-a.zip
(inside zip at top level there should be visible example-a
directory), start JLupin Next Server (start.sh/start.cmd
) and run control (control.sh/control.cmd
). Copy created zip file example-a.zip
into upload
directory. Then from control window run command microservice upload example-a.zip
. Your microservice will be uploaded to server and started. You can significantly speed up this process with our JCS JLupin Next Server Maven Plugin and also with our JCS JLupin Next Server IntelliJ Plugin.
integration-test
At first create base class for tests where you will provide servers where microservice is deployed for testing:
package com.example.base;
import com.jlupin.common.communication.common.various.JLupinMainServerInZoneConfiguration;
import com.jlupin.impl.client.util.JLupinClientUtil;
import com.jlupin.impl.logger.impl.log4j.JLupinLoggerOverLog4jImpl;
import com.jlupin.impl.serialize.JLupinFSTSerializerImpl;
import com.jlupin.interfaces.client.delegator.JLupinDelegator;
import com.jlupin.interfaces.common.enums.PortType;
import com.jlupin.interfaces.logger.JLupinLogger;
import com.jlupin.interfaces.serialize.JLupinSerializer;
import org.junit.Before;
public abstract class BaseTest {
private final JLupinDelegator jLupinDelegator;
public BaseTest() {
jLupinDelegator = JLupinClientUtil.generateOuterMicroserviceLoadBalancerDelegator(
PortType.JLRMC,
new JLupinMainServerInZoneConfiguration[]{
new JLupinMainServerInZoneConfiguration("NODE_1", "127.0.0.1", 9090, 9095, 9096, 9097)
}
);
}
public JLupinDelegator getJLupinDelegator() {
return jLupinDelegator;
}
}
Now you can define your microservice test:
package com.example;
import com.example.base.BaseTest;
import com.example.service.interfaces.AService;
import com.jlupin.impl.client.util.JLupinClientUtil;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ExampleATest extends BaseTest {
private AService getAService() {
return JLupinClientUtil.generateRemote(getJLupinDelegator(), "example-a", "aService", AService.class);
}
@Test
public void callATest() {
AService aService = getAService();
assertEquals("[called A][called B]input", aService.callA("input"));
}
}
And you can configure Log4j2 to log to standard out. Put this file (log4j2.xml
) into resources:
<?xml version="1.0" encoding="UTF-8"?>
<!-- ===================================================================== -->
<!-- -->
<!-- Log4j2 Configuration -->
<!-- -->
<!-- ===================================================================== -->
<!--
| For more configuration information and examples see the Apache Log4j2
| website: https://logging.apache.org/log4j/2.x/index.html
-->
<Configuration status="WARN">
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<!-- The default pattern: Date Priority [Category] (Thread) Message\n -->
<PatternLayout pattern="%d %-5p [%c] (%t) %m%n"/>
</Console>
<!-- AsyncAppender for high performance -->
<Async name="ASYNC_STDOUT">
<BufferSize>1000</BufferSize>
<AppenderRef ref="STDOUT"/>
</Async>
</Appenders>
<Loggers>
<!-- Setup for root logger with AsyncAppender -->
<Root level="info">
<AppenderRef ref="ASYNC_STDOUT"/>
</Root>
</Loggers>
</Configuration>
As said before microservice is called as from outer client (see base test constructor and line jLupinDelegator = JLupinClientUtil.generateOuterMicroserviceLoadBalancerDelegator(
).
Test execution
Before running test make sure that you microservices (example-a
and example-b
) are deployed on server pointed by your base test class. Then execute callATest
and see result.
JUnit version 4.12
.2017-09-26 12:00:23,930 INFO [com.jlupin.impl.balancer.ext.impl.roundrobin.JLupinRoundRobinLoadBalancerImpl$1] (pool-2-thread-1) MESSAGE ID:52 METHOD:call LINE:83 LOG:compute current node thread started correctly
2017-09-26 12:00:23,930 INFO [com.jlupin.impl.balancer.base.JLupinBaseLoadLoadBalancer$2] (pool-1-thread-1) MESSAGE ID:142 METHOD:call LINE:509 LOG:microservice discovery control thread started correctly
Time: 0,731
OK (1 test)