ElasticSearch Spring Data unit Test - junit

i am trying to unit test my spring data elasticsearch operation, but everytime getting null pointers.
i want to do it for the coverage of my code.
i am only using searching operations that is why i am using the elaststic operations, is there a way to unit test it with mokito.
i will share the snipit of the code :-
public Map < String, Object > articleRecommendation(SearchDocModel searchDocModel, int start, int size,
FiltersForRecommendation filtersForRecommendation) throws IOException {
Pageable pageable = PageRequest.of(start, size);
XContentBuilder xContentBuilderTitle = XContentFactory.jsonBuilder()
.startObject()
.field("", searchDocModel.getTitle())
.field("", searchDocModel.getAbstract())
.endObject();
MoreLikeThisQueryBuilder.Item titleItem = new MoreLikeThisQueryBuilder
.Item("", xContentBuilderTitle);
MoreLikeThisQueryBuilder.Item[] items = {
titleItem
};
MoreLikeThisQueryBuilder mltQuery = QueryBuilders.moreLikeThisQuery(items)
.minTermFreq(1)
.maxQueryTerms(25)
.minimumShouldMatch("30%")
.minDocFreq(5);
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery().must(mltQuery);
Query boolQuery = new NativeSearchQueryBuilder()
.withQuery(filters(boolQueryBuilder, filtersForRecommendation))
.withPageable(pageable)
.build();
return queryResult(boolQuery, pageable);
}
My test class
#Test
void articleRecommendation() throws IOException {
ElasticsearchOperations elasticsearchOperations = Mockito.mock(ElasticsearchOperations.class);
Pageable pageable = PageRequest.of(1, 1);
ElasticServiceImpl elasticService1 = new ElasticServiceImpl(elasticsearchOperations);
SearchHits searchHits = Mockito.mock(SearchHits.class);
SearchPage searchPage = Mockito.mock(SearchPage.class);
SearchHit searchHit = Mockito.mock(SearchHit.class);
when(searchHits.iterator()).thenReturn(singleton(searchHit).iterator());
when(elasticService1.articleRecommendation(apiModel, 1, 1, filtersForRecommendation))
.thenReturn(result);
}
exception i am getting:
java.lang.NullPointerException: Cannot invoke "org.springframework.data.elasticsearch.core.SearchHits.getSearchHits()" because "searchHits" is null
so how do i mock it property ? for code coverage

Related

Mocking a mongo find query and java into method

I have following query in the method:
public String getWrapperAttribute(String id, int counter) {
List<ResWrapper> wrapperList = new ArrayList<>();
String key = "Test";
String id = "Test";
objcollection.find(eq(key, id)).comment("Running the first query").into(wrapperList);
if (wrapperList.size() > 0) {
ResWrapper wrapperObj = wrapperList.get(0);
return wrapperObj .getField().getAttribute();
}
I want to unit test the method and want to mock the find query but keep getting NPE.
My unit test method:
#InjectMocks
Reader reader;
#Mock
MongoCollection<ResWrapper>objcollection;
#Mock
FindIterable<ResWrapper> findIterable;
#Test
public void getWrapperAttribute_Test() {
MongoCursor cursor = mock(MongoCursor.class);
ArrayList<ResWrapper> wrapperList = new ArrayList<>();
ResWrapper resWrapper = new ResWrapper();
Res res = new Res();
Res.setAttribute("1234545");
ResWrapper.setField(res);
WrapperList.add(ResWrapper);
Bson filter1 = eq("Test","Test");
when(objcollection.find(filter1)).thenReturn(findIterable);
when(findIterable.into(new ArrayList<>())).thenReturn(WrapperList)
reader.getWrapperAttribute("Test", 1);
}
I keep getting there is no find(Bson) for the type reader.
Is there anyway around this, this is existing code, just writing junit test case for it.

PageableHandlerMethodArgumentResolver in unit test does not parse sort direction

I have the controller and unit test shown below. The controller returns a sorted list. In the unit test, the sort field is passed correctly; however, the sort direction is not being parsed:
I am following these examples:
Isolated Controller Test can't instantiate Pageable
4. Paging and Sorting
Controller:
#RequestMapping("/telemetry")
public Page<TelemetryMessage> List(Pageable pageable) {
return telemetryMessageRepository.findAll(pageable);
}
Unit Test:
#Before
public void setUp() throws Exception {
mvc = MockMvcBuilders
.standaloneSetup(new TelemetryController(telemetryMessageRepository))
.setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
.setViewResolvers(new ViewResolver() {
#Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
return new MappingJackson2JsonView();
}
})
.build();
// etc.
}
#Test
public void testListReturnsDefault20() throws Exception {
Iterable<TelemetryMessage> expected = telemetryMessageRepository.findAll(new PageRequest(0, 20, Sort.Direction.DESC, "id"));
String json = mapper.writeValueAsString(expected);
MvcResult result = mvc.perform(MockMvcRequestBuilders.get("/telemetry")
.param("sort", "id")
.param("id.dir", "desc")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn();
String actual = result.getResponse().getContentAsString();
}
Use comma to separate the Property and the Direction, like following:
MvcResult result = mvc.perform(MockMvcRequestBuilders.get("/telemetry")
.param("sort", "id,desc")
//.param("id.dir", "desc")

Junit Test unable to load Properties File

I'm trying to run a simple test to check values in a properties file which I've saved in the src/test/resources folder of my Maven project but the JUnit test is failing. My test is picking up the File OK but it doesn't return the expected value as the file doesn't look like its getting loaded. Anyone else have a similar issue? My code/test are as follows:
My Application Context File:
<bean id="myProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:test.properties"/>
</bean>
My Code:
#Resource(name = "myProps") private Properties myProps;
#Value("#{myProps['totalNumberOfChanges']}") private String totalNumberOfChangesStr;
#Value("#{myProps['delayTime']}") private String delayTimeStr;
public void parseAttributesFromConfigFile() {
String methodName = "parsePropertyAttributesFromConfigFile";
try {
totalNumberOfChanges = Integer.parseInt(totalNumberOfChangesStr);
delayTime = Integer.parseInt(delayTimeStr);
numEntriesToIterateThru = (totalNumberOfChanges / delayTime);
} catch (NumberFormatException nfe) {
LOGGER.error(methodName, "", "Number Format Exception Occured" + nfe.getMessage());
}
}
My Junit Test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:META-INF/spring/Testpu.xml" })
public class ConfigPropertiesTest {
private final int NUM_ENTRIES_TO_ITERATE_THRU = 100;
private final int TOTAL_NUMBER_OF_CHANGES = 100000;
private final int DELAY_TIME = 1000;
private ConfigProperties configProperties;
#Before
public void setUp() throws Exception {
configProperties = new ConfigProperties();
}
#Test
public final void testParseAttributesFromConfigFileIsCalled() {
configProperties.parseAttributesFromConfigFile();
int numEntriesToIterateOver = configProperties.getNumEntriesToIterateThru();
assertEquals(numEntriesToIterateOver, NUM_ENTRIES_TO_ITERATE_THRU);
int numberOfChanges = configProperties.getTotalNumberOfChanges();
assertEquals(numberOfChanges, TOTAL_NUMBER_OF_CHANGES);
int delayTime = configProperties.getDelayTime();
assertEquals(delayTime, DELAY_TIME);
}
}
You are creating the ConfigProperties class in your Before method. If you want Spring to populated values based on annotations the bean must be created as part of the Spring context. If you have an instance of ConfigProperties in your Spring context, load that instance into your test using #Autowired

Camel route loop not working

I am trying to insert json data in mySQL database using camel and hibernate.
Everything is working.
for (Module module : modules) {
from("timer://foo?delay=10000")
.loop(7)//not working
.to(module.getUrl() + "/api/json")
.convertBodyTo(String.class)
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
int index = (Integer)exchange.getProperty("CamelLoopIndex"); // not working
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(exchange.getIn().getBody().toString());
String[] lijst = {"lastBuild", "lastCompletedBuild", "lastFailedBuild", "lastStableBuild", "lastSuccessfulBuild", "lastUnstableBuild", "lastUnsuccessfulBuild"};
JSONObject obj = new JSONObject();
JsonNode node = root.get(lijst[index]);
JsonNode build = node.get("number");
obj.put("description", lijst[index]);
obj.put("buildNumber", build);
exchange.getIn().setBody(obj.toString());
}
})
.unmarshal(moduleDetail)
.to("hibernate:be.kdg.teamf.model.ModuleDetail")
.end();
}
When I debug, my CamelLoopIndex remains 0 so it is not incremented every time it goes through the loop.
All help is welcome!
In your case the only first instruction is processed in scope of the loop: .to(module.getUrl() + "/api/json"). You can add more instructions into a loop using Spring DSL, but I don't know how to declare a loop scope using Java DSL explicitly. I hope experts will explain more about a loop scope in Java DSL.
As a workaround I suggest to move all iteration instructions to a separate direct: route.
I can't reproduce your problem. This works:
from("restlet:http://localhost:9010}/loop?restletMethod=get")
.loop(7)
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
int index = (int) exchange.getProperty("CamelLoopIndex");
exchange.getIn().setBody("index=" + index);
}
})
.convertBodyTo(String.class)
.end();
Output:
index=6

Jedis Pipeline Multi throws ClassCastException

public class JedisPipeline {
private static JedisPool pool = new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379);
public static void main(String args[]){
Jedis jedis = pool.getResource();
Pipeline pipeline = jedis.pipelined();
pipeline.multi();
//pipeline.hmset("Id", new HashMap<String,String>() );
for(int i=0; i < 1000 ; i++){
pipeline.hincrBy("Id", i+"", i);
}
pipeline.exec();
pool.returnResource(jedis);
//pool.destroy();
//pool = new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379);
jedis = pool.getResource();
Map<String,String> map1 = jedis.hgetAll("Id");
System.out.println("map1------->"+map1);
pool.returnResource(jedis);
//pool.destroy();
}
}
I have a problem in the above code. It throws a ClassCastException, where as if I destroy the pool and create a new pool object it works properly. Am I using the Pipeline API properly ?. Can anyone help me ? I am using Jedis 2.1.0
Exception in thread "main" java.lang.ClassCastException: [B cannot be cast to java.util.List
at redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:189)
at redis.clients.jedis.Jedis.hgetAll(Jedis.java:861)
at com.work.jedisex.JedisFactory.main(JedisFactory.java:59)
Modified code to get the Map which throws Exception
Response<Map<String,String>> map1 = pipeline.hgetAll("Id");
pipeline.exec();
pipeline.sync();
pool.returnResource(jedis);
Map<String,String> map2 = map1.get();
Looks like the pipeline doesn't close after exec() call. So when you try to reuse the same Jedis object after returnResource it still contains pipelinedResponses from previous operation.
Try to do this way:
pipeline.exec();
pipeline.sync();
pool.returnResource(jedis);
sync() call should close the pipeline.