问题
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.
回答1:
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.
来源:https://stackoverflow.com/questions/64589066/how-to-mock-elasticsearchoperations-spring-data-elasticsearch-v-4-0-3-when-uni