Spring boot docker testcontainers keep starting new containers on VDS - spring-boot

So i have issued with very strange problem, I use testcontainers to start app and database instance while testing. On my pc (Mac), on my second pc which has Windows and even on computer with Ubuntu everything works as expected.
Then I started to use github actions to initiate tests every time someone tries to make merge request to master branch. And here I have problem.
I will skip github actions code part because It won't pass tests even with basic gradlew test clean command.
So behavior I expect:
I write gradlew test clean
Spring starts application container and database container. (And it works everywhere except my VDS, where it must work)
What behavior I get on VDS:
I write gradlew test clean
Spring starts application container and database container.
Spring for some reason can't connect to database container and starts another database container (timeout 2 minutes)
During tests Spring creates 4-5 database containers and without any success to connect with them fails all tests (as expected without working DB)
Every test file has following database configuration:
#SpringBootTest
#AutoConfigureMockMvc
#Testcontainers
#ContextConfiguration(initializers = {UserDataControllerTest.Initializer.class})
#TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class UserDataControllerTest {
#Autowired
private MockMvc mockMvc;
#Autowired
private ObjectMapper objectMapper;
#ClassRule
#Container
public final static MySQLContainer mysqlContainer = new MySQLContainer("mysql:8.0");
... some tests
static class Initializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
TestPropertyValues.of(
"spring.datasource.url=" + mysqlContainer.getJdbcUrl(),
"spring.datasource.username=" + mysqlContainer.getUsername(),
"spring.datasource.password=" + mysqlContainer.getPassword(),
"spring.jpa.generate-ddl=true",
"spring.jpa.hibernate.ddl-auto=create-drop"
).applyTo(configurableApplicationContext.getEnvironment());
}
}
}
Stacktrace I get after command finishes:
org.testcontainers.containers.ContainerLaunchException: Container startup failed
at app//org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:336)
at app//org.testcontainers.containers.GenericContainer.start(GenericContainer.java:317)
at app//org.testcontainers.junit.jupiter.TestcontainersExtension$StoreAdapter.start(TestcontainersExtension.java:242)
at app//org.testcontainers.junit.jupiter.TestcontainersExtension$StoreAdapter.access$200(TestcontainersExtension.java:229)
at app//org.testcontainers.junit.jupiter.TestcontainersExtension.lambda$null$1(TestcontainersExtension.java:59)
at app//org.junit.jupiter.engine.execution.ExtensionValuesStore.lambda$getOrComputeIfAbsent$4(ExtensionValuesStore.java:86)
at app//org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.computeValue(ExtensionValuesStore.java:223)
at app//org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.get(ExtensionValuesStore.java:211)
at app//org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.evaluate(ExtensionValuesStore.java:191)
at app//org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.access$100(ExtensionValuesStore.java:171)
at app//org.junit.jupiter.engine.execution.ExtensionValuesStore.getOrComputeIfAbsent(ExtensionValuesStore.java:89)
at app//org.junit.jupiter.engine.execution.NamespaceAwareStore.getOrComputeIfAbsent(NamespaceAwareStore.java:53)
at app//org.testcontainers.junit.jupiter.TestcontainersExtension.lambda$beforeAll$2(TestcontainersExtension.java:59)
at java.base#17.0.4/java.util.ArrayList.forEach(ArrayList.java:1511)
at app//org.testcontainers.junit.jupiter.TestcontainersExtension.beforeAll(TestcontainersExtension.java:59)
at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$10(ClassBasedTestDescriptor.java:381)
at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:381)
at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:205)
at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:80)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:148)
at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base#17.0.4/java.util.ArrayList.forEach(ArrayList.java:1511)
at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at java.base#17.0.4/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base#17.0.4/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base#17.0.4/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base#17.0.4/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
at app//org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:88)
at app//org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:329)
... 69 more
Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
at app//org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:525)
at app//org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:331)
at app//org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
... 70 more
Caused by: java.lang.IllegalStateException: Container is started, but cannot be accessed by (JDBC URL: jdbc:mysql://localhost:49156/test), please check container logs
at org.testcontainers.containers.JdbcDatabaseContainer.waitUntilContainerStarted(JdbcDatabaseContainer.java:165)
at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:468)
... 72 more
PS. I multiple times reinstalled OS on VDS, there was Debian and now Ubuntu. Docker was installed by the instruction on the official website, user which starts github actions added to docker group (it actually doesn't matter because it won't start even from root user)

Related

Unable to start eureka sever using sping cloud config server

I am working on a micro service based on spring boot
Now i have two services
configserver
discoveryserver
coreservice
I can able to start configserver and coreserver.Both are working fine.coreserver taking configuration from configserver. All properties are save on my file system as an application properties
configurations
when i run my discoveryserver it showing below error
20:52:34.918 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.IllegalStateException: Unable to load config data from 'configserver:'
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferences(StandardConfigDataLocationResolver.java:141)
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferences(StandardConfigDataLocationResolver.java:126)
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.resolve(StandardConfigDataLocationResolver.java:119)
at org.springframework.boot.context.config.ConfigDataLocationResolvers.lambda$resolve$1(ConfigDataLocationResolvers.java:115)
at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:126)
at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:115)
at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:107)
at org.springframework.boot.context.config.ConfigDataImporter.resolve(ConfigDataImporter.java:105)
at org.springframework.boot.context.config.ConfigDataImporter.resolve(ConfigDataImporter.java:97)
at org.springframework.boot.context.config.ConfigDataImporter.resolveAndLoad(ConfigDataImporter.java:85)
at org.springframework.boot.context.config.ConfigDataEnvironmentContributors.withProcessedImports(ConfigDataEnvironmentContributors.java:116)
at org.springframework.boot.context.config.ConfigDataEnvironment.processInitial(ConfigDataEnvironment.java:240)
at org.springframework.boot.context.config.ConfigDataEnvironment.processAndApply(ConfigDataEnvironment.java:227)
at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:102)
at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:94)
at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:102)
at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:87)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:85)
at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:66)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:114)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:65)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:344)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
at com.nielsen.discoveryserver.DiscoveryServerApplication.main(DiscoveryServerApplication.java:12)
Caused by: java.lang.IllegalStateException: File extension is not known to any PropertySourceLoader. If the location is meant to reference a directory, it must end in '/' or File.separator
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferencesForFile(StandardConfigDataLocationResolver.java:229)
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferences(StandardConfigDataLocationResolver.java:138)
... 31 common frames omitted
Process finished with exit code 1
discovery server application.properties
spring.cloud.config.uri= http://localhost:8888
spring.application.name = discoveryserver
spring.config.import = configserver:
spring.profiles.active= native
configuration repository properties named same as application name
discoveryserver.properties
server.port =8081
mian class
#SpringBootApplication
#EnableEurekaServer
public class DiscoveryServerApplication {
public static void main(String[] args) {
SpringApplication.run(DiscoveryServerApplication.class, args);
}
}
coreserver have the similar configurations.its working file for me.i coudn't understand why discoveryserver throwing error.
Help on this issue.
Thanks in advance.

Spring 5.2.x to 5.3.x upgrade cause ClassNotFoundException for Quartz Jobs under Wildlfy 20

We are using:
JDK 8
Spring 5.2.16.RELEASE
Quartz - 2.3.2
Wildfly 20
Apart from the web application(.war) we have also plugins (.jar) for which the classes are loaded with the following code in the web app:
Thread.currentThread().setContextClassLoader(pluginsClassLoader);
PluginsClassLoader extends URLClassLoader
We are using
org.springframework.scheduling.quartz.QuartzBean to define our own quartz jobs both in the war in the plugins (.jar) e.g. FSSendMessagesWorker extends QuartzBean
in a #Configuration class we have
#Bean
public JobDetailFactoryBean fsPluginSendMessagesWorkerJob() {
JobDetailFactoryBean obj = new JobDetailFactoryBean();
obj.setJobClass(FSSendMessagesWorker.class);
obj.setDurability(true);
return obj;
}
#Bean
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public SimpleTriggerFactoryBean fsPluginSendMessagesWorkerTrigger()
SimpleTriggerFactoryBean obj = new SimpleTriggerFactoryBean();
obj.setJobDetail(fsPluginSendMessagesWorkerJob().getObject());
obj.setRepeatInterval("* * * 0 1");
obj.setStartDelay(20000);
return obj;
}
After upgrading to Spring 5.3.x it looks like the all classes which extends QuartzBean and present in the .jar files could not be loaded while this was possible (worked) before in Spring 5.2.x
The ones present in the main app (.war) just works fain - are loaded.
Apart from Spring no other library was upgraded.
021-10-05 14:03:25,055 [] [] [] [EE-ManagedExecutorService-quartzExecutorService-Thread-1] ERROR o.s.s.q.LocalDataSourceJobStore:2867 - Error retrieving job, setting trigger state to ERROR.
org.quartz.JobPersistenceException: Couldn't retrieve job because a required class was not found: com.company.plugin.fs.worker.FSSendMessagesWorker from [Module "deployment.mycompany.war" from Service Module Loader]
at deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1393)
at deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2864)
at deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport$41.execute(JobStoreSupport.java:2805)
at deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport$41.execute(JobStoreSupport.java:2803)
at deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3864)
at deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTriggers(JobStoreSupport.java:2802)
at deployment.mycompany.war//org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:287)
at org.jboss.as.ee#20.0.1.Final//org.jboss.as.ee.concurrent.ControlPointUtils$ControlledRunnable.run(ControlPointUtils.java:105)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at org.glassfish.javax.enterprise.concurrent//org.glassfish.enterprise.concurrent.internal.ManagedFutureTask.run(ManagedFutureTask.java:117)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
at org.glassfish.javax.enterprise.concurrent//org.glassfish.enterprise.concurrent.ManagedThreadFactoryImpl$ManagedThread.run(ManagedThreadFactoryImpl.java:227)
Caused by: java.lang.ClassNotFoundException: com.company.plugin.fs.worker.FSSendMessagesWorker from [Module "deployment.mycompany.war" from Service Module Loader]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:255)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:398)
at deployment.domibus-MSH-wildfly-5.0-SNAPSHOT.war//org.springframework.util.ClassUtils.forName(ClassUtils.java:284)
at deployment.domibus-MSH-wildfly-5.0-SNAPSHOT.war//org.springframework.scheduling.quartz.ResourceLoaderClassLoadHelper.loadClass(ResourceLoaderClassLoadHelper.java:81)
at deployment.domibus-MSH-wildfly-5.0-SNAPSHOT.war//org.springframework.scheduling.quartz.ResourceLoaderClassLoadHelper.loadClass(ResourceLoaderClassLoadHelper.java:87)
at deployment.domibus-MSH-wildfly-5.0-SNAPSHOT.war//org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:852)
at deployment.domibus-MSH-wildfly-5.0-SNAPSHOT.war//org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1390)
The quartz has the option to register class loader via the property:
org.quartz.scheduler.classLoadHelper.class
In case setting the TCCL Transaction Context ClassLoader, make sure the cron thread has the same class loader as the class loader, which loads the "classes." In WildFly new threads, get ModuleClassLoader which can have different class scope than the one set back to thread scope in the initial stage.
Try with:
org.quartz.scheduler.classLoadHelper.class = org.quartz.simpl.InitThreadContextClassLoadHelper
Or write a custom ClassHelperLoader class.
https://www.quartz-scheduler.org/api/2.0.2/org/quartz/spi/ClassLoadHelper.html

How to mock ElasticsearchOperations (spring-data-elasticsearch v.4.0.3) when unit testing

I am working on a project that uses Spring 2.3.3, spring-data-elastic-4.0.3, ElasticSearch 7.9.0 and mockito-core 3.3.3
I'm trying to mock ElasticsearchOperations when writing unit tests, this is the Service I would like to test (where it's used ElasticsearchOperations):
#Service
public class SearchByLabelServiceImpl implements SearchByLabelService {
private ElasticsearchOperations elasticsearchTemplate;
public SearchByLabelServiceImpl(ElasticsearchOperations elasticsearchTemplate) {
this.elasticsearchTemplate = elasticsearchTemplate;
}
public SearchPage<TagResponse> searchByLabel(String query, List<String> labelsToExclude, boolean shouldIncludeDescription, Pageable pageable) {
....
enter code here
var result = elasticsearchTemplate.search(nativeSearchQuery, TagResponse.class, IndexCoordinates.of(tagIndexName));
}
And this is the Test class:
#RunWith(SpringRunner.class)
#SpringBootTest
#ActiveProfiles(profiles = "test")
public class SearchByLabelServiceImplTest {
private ElasticsearchOperations elasticsearchTemplate = mock(ElasticsearchOperations.class);
private SearchByLabelService searchByLabelService = new SearchByLabelServiceImpl(elasticsearchTemplate);
#Test
#Ignore
public void shouldReturnTheTagsBasedOnSearchRequestIncludingDescription() {
...//Arrange
when(elasticsearchTemplate.search(queryArgumentCaptor.capture(), eq(TagResponse.class), IndexCoordinates.of(tagIndexName))).thenReturn(searchHitsResponse);
var searchResponse = searchByLabelService.searchByLabel(testSearchQuery, testLabelsToExcludeList, true, PageRequest.of(1, 1));
....
//Assertions
}
And the error I get is this one:
org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: interface org.springframework.data.elasticsearch.core.ElasticsearchOperations.
Mockito can only mock non-private & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.
Java : 11
JVM vendor name : Oracle Corporation
JVM vendor version : 11.0.5+10-LTS
JVM name : Java HotSpot(TM) 64-Bit Server VM
JVM version : 11.0.5+10-LTS
JVM info : mixed mode
OS name : Mac OS X
OS version : 10.15.7
Underlying exception : java.lang.TypeNotPresentException: Type org.elasticsearch.cluster.metadata.AliasMetaData not present
at com.optum.genesis.tag.service.SearchByLabelServiceImplTest.<init>(SearchByLabelServiceImplTest.java:41)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:250)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:226)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.TypeNotPresentException: Type org.elasticsearch.cluster.metadata.AliasMetaData not present
Many thanks in advance.
You are using Spring Data Elasticsearch 4.0.3 which was built with Elasticsearch library 7.6.2, but during the runtime you are providing Elasticsearch 7.9.0.
Elasticsearch had a little breaking change in their code between 7.6 and 7.9:
The class org.elasticsearch.cluster.metadata.AliasMetaData was renamed to org.elasticsearch.cluster.metadata.AliasMetadata - please notice the change from D to d in Metadata.
So what can you do? Why do you need to use the Elasticsearch libs in 7.9? If you cluster is running on 7.9, you could probably still access it with client libs from 7.6.
Or you update your application to use Spring Data Elasticsearch 4.1 which was released yesterday.
You could wrap the ElasticsearchOperations in a new class you could create (eg ElasticsearchOperationsWrapper) where you would expose the methods you need and in your code, wherever you invoked ElasticsearchOperations replace it by ElasticsearchOperationsWrapper and then you could mock it normally. ;)

JUnit test case error: "Address already in use: bind"

I have a JUnit test case for my Project which is developed using
SpringBoot (1.3.5) & JDK 8. When I run my project as JUnit test in STS, all
test cases pass, but gives error at the end of each test cases, which
is: I am trying to run JUnit Coverage:
ERROR [ main] o.a.coyote.http11.Http11NioProtocol o.a.j.l.DirectJDKLog.log(DirectJDKLog.java:182) - |||||||||Failed to start end point associated with ProtocolHandler ["http-nio-8080"]
java.net.BindException: Address already in use: bind
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:433)
at sun.nio.ch.Net.bind(Net.java:425)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:340)
at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:773)
at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:473)
at org.apache.catalina.connector.Connector.startInternal(Connector.java:986)
........
........
........
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
ERROR [ main] o.apache.catalina.core.StandardService o.a.j.l.DirectJDKLog.log(DirectJDKLog.java:182) - |||||||||Failed to start connector [Connector[HTTP/1.1-8080]]
org.apache.catalina.LifecycleException: Failed to start component [Connector[HTTP/1.1-8080]]
This error shows as the port 8080 is already in use. How to avoid this
error and let my all 20 test cases to run in one flow without this
error?
My code is:--->
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(KYCNotificationApplication.class)
#ActiveProfiles("local")
#WebIntegrationTest
#IntegrationTest({"server.port=0"})
public class DetermineKYCNotificationServiceImplTest {
#InjectMocks
DetermineKYCNotificationServiceImpl kycService;
#Mock
KYCOperationsDao kycOperationsDao;
#Mock
HttpServletRequest httpServletRequest;
#Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
...
}
#Test
public void testMeth1() {
try {
.....
assertTrue(......);
} catch (Exception e) {
e.printStackTrace();
}
}
#Test
public void testMeth2() {
try {
.....
assertTrue(......);
} catch (Exception e) {
e.printStackTrace();
}
}
...2o more test cases....
In Spring Boot < 1.4 you can annotate your test class with #IntegrationTest({"server.port=0"})
In Spring Boot >= 1.4 you can use #SpringBootTest(classes = Application.class , webEnvironment=WebEnvironment.RANDOM_PORT).
Both approaches have the same effect, namely; Spring will assign a random port (and will magically update the application properties in your test context to reflect this test-specific port).
More details in the docs ...
If you need to start a full running server for tests, we recommend that you use random ports. If you use #SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) an available port will be picked at random each time your test runs.
The #LocalServerPort annotation can be used to inject the actual port used into your test. For convenience, tests that need to make REST calls to the started server can additionally #Autowire a TestRestTemplate which will resolve relative links to the running server.
Update 1: based on your updated question I can now see that you are using #WebIntegrationTest. In this case you could simply add the randomPort parameter to that annotation e.g.
#WebIntegrationTest(randomPort = true)

#LoadBalanced RestTemplate to call nested context endpoints

The below guide page is great and works as a base case for ribbon in a spring boot application.
https://spring.io/guides/gs/client-side-load-balancing/
The example stops working as soon as the endpoint mappings become nested - e.g. adding
#RequestMapping(value = "/welcome")
at the class level
#RestController
#SpringBootApplication
#RequestMapping(value = "/welcome") //<------------- ADDED --->
public class SayHelloApplication {
private static Logger log = LoggerFactory.getLogger(SayHelloApplication.class);
#RequestMapping(value = "/greeting")
public String greet() {
And then change the #LoadBalanced RestTemplate call in the client from
String greeting = this.restTemplate.getForObject("http://say-hello/greeting", String.class);
to
String greeting = this.restTemplate.getForObject("http://say-hello/welcome/greeting", String.class);
Calls are failing with attached stacktrace while directly acessing http://localhost:8090/welcome/greeting still works fine. What would be the appropriate way to configure ribbon to load balance requests to long and nested URL endpoints such as domain.com/x/y/z/p/q?
Stacktrace:
java.lang.IllegalStateException: No instances available for say-hello
at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:79) ~[spring-cloud-netflix-core-1.1.4.RELEASE.jar:1.1.4.RELEASE]
at org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor.intercept(LoadBalancerInterceptor.java:46) ~[spring-cloud-commons-1.1.1.RELEASE.jar:1.1.1.RELEASE]
at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:85) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:69) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:596) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:264) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at hello.UserApplication.hi(UserApplication.java:31) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]
The issue is by adding #RequestMapping to the class you also changed the / handler to move from the root to /welcome/. To make it so the load balancer can keep working you have to update the PingUrl being used within the SayHelloConfiguration of the user app. Make it new PingUrl(false, "/welcome/")
I was also using this sample application to get started with Ribbon which is great.
To make it clear, I'd like to spend a bit more words on the design:
The user application, under "/complete/user" folder, is the
"client" application and we can access it via "curl
http://{host}:8888"; while the say-hello application, under
"/complete/say-hello" folder, is the "service provider". As
instructed by the example, we should spin up 3 instances via
{host}:8090, {host}:9092 and {host}:9999 -- we can check out
/complete/user/src/main/resources/application.yml to have a look;
Ribbon, embedded in "client" user application, will maintain a series load balancing service instances (here will be 3 if we spin up the instances as mentioned above) by the default Ping strategy, which will periodically ping the service instances by calling a specific URL. By default is the "/" as we can see the code here (again, which is configurable also by specifying the URI):
#Bean
public IPing ribbonPing(IClientConfig config) {
return new PingUrl();
}
Now, let's come back to your issue.
Once you have changed the URI mapping in SayHelloApplication.java by adding explicitly the #RequestMapping(value = "/welcome"), the mapping for "/" in
#RequestMapping(value = "/")
public String home() {
log.info("Access /");
return "Hi!";
}
will mean the root path under "/welcome" which is "/welcome/", not the "/" of the say-hello application.
Then we don't have any mapping for the real "/" which is, for example, 'http://{host}:8090/'. In this case, the Ping will fail one by one and eventually Ribbon will mark all the service instances unhealthy so you end up with "No instances available for say-hello".

Resources