org.springframework.data.solr.core.SolrTemplateTests.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.data.solr.core.SolrTemplateTests.java

Source

/*
 * Copyright 2012 - 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.data.solr.core;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.http.ParseException;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.SolrPingResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.hamcrest.core.Is;
import org.hamcrest.core.IsEqual;
import org.hamcrest.core.IsNull;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.convert.converter.Converter;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.solr.UncategorizedSolrException;
import org.springframework.data.solr.core.mapping.Indexed;
import org.springframework.data.solr.core.mapping.SolrDocument;
import org.springframework.data.solr.core.query.Criteria;
import org.springframework.data.solr.core.query.PartialUpdate;
import org.springframework.data.solr.core.query.Query;
import org.springframework.data.solr.core.query.SimpleQuery;
import org.springframework.data.solr.core.query.SimpleStringCriteria;
import org.springframework.data.solr.core.query.SolrDataQuery;
import org.springframework.data.solr.core.schema.SolrPersistentEntitySchemaCreator.Feature;
import org.springframework.data.solr.core.schema.SolrSchemaRequest;
import org.springframework.data.solr.repository.Score;
import org.springframework.data.solr.server.SolrServerFactory;

/**
 * @author Christoph Strobl
 * @author Joachim Uhrlass
 * @author Francisco Spaeth
 */
@RunWith(MockitoJUnitRunner.class)
public class SolrTemplateTests {

    private SolrTemplate solrTemplate;

    private static final SimpleJavaObject SIMPLE_OBJECT = new SimpleJavaObject("simple-string-id", 123l);
    private static final SimpleBoostedJavaObject SIMPLE_BOOSTED_OBJECT = new SimpleBoostedJavaObject(
            "simple-string-id", 123l, "simple-string-boost");
    private static final SolrInputDocument SIMPLE_DOCUMENT = new SolrInputDocument();

    private @Mock SolrServer solrServerMock;

    @Before
    public void setUp() {
        solrTemplate = new SolrTemplate(solrServerMock, "core1");
        solrTemplate.afterPropertiesSet();
    }

    @Test(expected = IllegalArgumentException.class)
    public void testNullServerFactory() {
        new SolrTemplate((SolrServerFactory) null);
    }

    @Test
    public void testPing() throws SolrServerException, IOException {
        Mockito.when(solrServerMock.ping()).thenReturn(new SolrPingResponse());
        SolrPingResponse pingResult = solrTemplate.ping();
        Assert.assertNotNull(pingResult);
        Mockito.verify(solrServerMock, Mockito.times(1)).ping();
    }

    @Test(expected = DataAccessException.class)
    public void testPingThrowsException() throws SolrServerException, IOException {
        Mockito.when(solrServerMock.ping())
                .thenThrow(new SolrServerException("error", new SolrException(ErrorCode.NOT_FOUND, "not found")));
        solrTemplate.ping();
    }

    @Test(expected = InvalidDataAccessApiUsageException.class)
    public void testQueryThrowsParseException() throws SolrServerException {
        Mockito.when(solrServerMock.query(Matchers.any(SolrParams.class))).thenThrow(new SolrServerException(
                "error", new SolrException(ErrorCode.BAD_REQUEST, new ParseException("parse error"))));
        solrTemplate.executeSolrQuery(new SolrQuery());
    }

    @Test(expected = UncategorizedSolrException.class)
    public void testQueryThrowsUntranslateableException() throws SolrServerException {
        Mockito.when(solrServerMock.query(Matchers.any(SolrParams.class))).thenThrow(new SecurityException());
        solrTemplate.executeSolrQuery(new SolrQuery());
    }

    @Test
    public void testSaveBean() throws IOException, SolrServerException {
        Mockito.when(solrServerMock.add(Mockito.any(SolrInputDocument.class), Mockito.eq(-1)))
                .thenReturn(new UpdateResponse());
        UpdateResponse updateResponse = solrTemplate.saveBean(SIMPLE_OBJECT);
        Assert.assertNotNull(updateResponse);

        ArgumentCaptor<SolrInputDocument> captor = ArgumentCaptor.forClass(SolrInputDocument.class);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(captor.capture(), Mockito.eq(-1));

        Assert.assertEquals(SIMPLE_OBJECT.getId(), captor.getValue().getFieldValue("id"));
        Assert.assertEquals(SIMPLE_OBJECT.getValue(), captor.getValue().getFieldValue("value"));
    }

    @Test
    public void testSaveBeanCommitWithin() throws IOException, SolrServerException {
        Mockito.when(solrServerMock.add(Mockito.any(SolrInputDocument.class), Mockito.eq(10000)))
                .thenReturn(new UpdateResponse());
        UpdateResponse updateResponse = solrTemplate.saveBean(SIMPLE_OBJECT, 10000);
        Assert.assertNotNull(updateResponse);

        ArgumentCaptor<SolrInputDocument> captor = ArgumentCaptor.forClass(SolrInputDocument.class);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(captor.capture(), Mockito.eq(10000));

        Assert.assertEquals(SIMPLE_OBJECT.getId(), captor.getValue().getFieldValue("id"));
        Assert.assertEquals(SIMPLE_OBJECT.getValue(), captor.getValue().getFieldValue("value"));
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testPartialUpdate() throws SolrServerException, IOException {
        Mockito.when(solrServerMock.add(Mockito.any(SolrInputDocument.class), Mockito.eq(-1)))
                .thenReturn(new UpdateResponse());

        PartialUpdate update = new PartialUpdate("id", "update-id");
        update.add("field_1", "update");

        solrTemplate.saveBean(update);
        ArgumentCaptor<SolrInputDocument> captor = ArgumentCaptor.forClass(SolrInputDocument.class);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(captor.capture(), Mockito.eq(-1));

        Assert.assertTrue(captor.getValue().getFieldValue("field_1") instanceof Map);
        Assert.assertEquals("update",
                ((Map<String, Object>) captor.getValue().getFieldValue("field_1")).get("set"));
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testSaveBeans() throws IOException, SolrServerException {
        Mockito.when(solrServerMock.add(Mockito.anyCollectionOf(SolrInputDocument.class), Mockito.eq(-1)))
                .thenReturn(new UpdateResponse());
        List<SimpleJavaObject> collection = Arrays.asList(new SimpleJavaObject("1", 1l),
                new SimpleJavaObject("2", 2l), new SimpleJavaObject("3", 3l));
        UpdateResponse updateResponse = solrTemplate.saveBeans(collection);
        Assert.assertNotNull(updateResponse);

        @SuppressWarnings("rawtypes")
        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(captor.capture(), Mockito.eq(-1));

        Assert.assertEquals(3, captor.getValue().size());
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testSaveBeansCommitWithin() throws IOException, SolrServerException {
        Mockito.when(solrServerMock.add(Mockito.anyCollectionOf(SolrInputDocument.class), Mockito.eq(10000)))
                .thenReturn(new UpdateResponse());
        List<SimpleJavaObject> collection = Arrays.asList(new SimpleJavaObject("1", 1l),
                new SimpleJavaObject("2", 2l), new SimpleJavaObject("3", 3l));
        UpdateResponse updateResponse = solrTemplate.saveBeans(collection, 10000);
        Assert.assertNotNull(updateResponse);

        @SuppressWarnings("rawtypes")
        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(captor.capture(), Mockito.eq(10000));

        Assert.assertEquals(3, captor.getValue().size());
    }

    @Test
    public void testSaveDocument() throws IOException, SolrServerException {
        Mockito.when(solrServerMock.add(Mockito.any(SolrInputDocument.class), Mockito.eq(-1)))
                .thenReturn(new UpdateResponse());
        UpdateResponse updateResponse = solrTemplate.saveDocument(SIMPLE_DOCUMENT);
        Assert.assertNotNull(updateResponse);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(Mockito.eq(SIMPLE_DOCUMENT), Mockito.eq(-1));
    }

    @Test
    public void testSaveDocumentCommitWithin() throws IOException, SolrServerException {
        Mockito.when(solrServerMock.add(Mockito.any(SolrInputDocument.class), Mockito.eq(10000)))
                .thenReturn(new UpdateResponse());
        UpdateResponse updateResponse = solrTemplate.saveDocument(SIMPLE_DOCUMENT, 10000);
        Assert.assertNotNull(updateResponse);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(Mockito.eq(SIMPLE_DOCUMENT), Mockito.eq(10000));
    }

    @Test
    public void testSaveDocuments() throws IOException, SolrServerException {
        Mockito.when(solrServerMock.add(Mockito.anyCollectionOf(SolrInputDocument.class), Mockito.eq(-1)))
                .thenReturn(new UpdateResponse());
        List<SolrInputDocument> collection = Arrays.asList(SIMPLE_DOCUMENT);
        UpdateResponse updateResponse = solrTemplate.saveDocuments(collection);
        Assert.assertNotNull(updateResponse);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(Mockito.eq(collection), Mockito.eq(-1));
    }

    @Test
    public void testSaveDocumentsCommitWithin() throws IOException, SolrServerException {
        Mockito.when(solrServerMock.add(Mockito.anyCollectionOf(SolrInputDocument.class), Mockito.eq(10000)))
                .thenReturn(new UpdateResponse());
        List<SolrInputDocument> collection = Arrays.asList(SIMPLE_DOCUMENT);
        UpdateResponse updateResponse = solrTemplate.saveDocuments(collection, 10000);
        Assert.assertNotNull(updateResponse);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(Mockito.eq(collection), Mockito.eq(10000));
    }

    @Test
    public void testDeleteById() throws IOException, SolrServerException {
        Mockito.when(solrServerMock.deleteById(Mockito.anyString())).thenReturn(new UpdateResponse());
        UpdateResponse updateResponse = solrTemplate.deleteById("1");
        Assert.assertNotNull(updateResponse);
        Mockito.verify(solrServerMock, Mockito.times(1)).deleteById(Mockito.eq("1"));
    }

    @Test
    public void testDeleteByIdWithCollection() throws IOException, SolrServerException {
        Mockito.when(solrServerMock.deleteById(Mockito.anyListOf(String.class))).thenReturn(new UpdateResponse());
        List<String> idsToDelete = Arrays.asList("1", "2");
        UpdateResponse updateResponse = solrTemplate.deleteById(idsToDelete);
        Assert.assertNotNull(updateResponse);

        @SuppressWarnings("unchecked")
        ArgumentCaptor<List<String>> captor = (ArgumentCaptor<List<String>>) (Object) ArgumentCaptor
                .forClass(List.class);

        Mockito.verify(solrServerMock, Mockito.times(1)).deleteById(captor.capture());

        Assert.assertEquals(idsToDelete.size(), captor.getValue().size());
        for (String s : idsToDelete) {
            Assert.assertTrue(captor.getValue().contains(s));
        }
    }

    @Test
    public void testCount() throws SolrServerException {
        ArgumentCaptor<SolrQuery> captor = ArgumentCaptor.forClass(SolrQuery.class);
        QueryResponse responseMock = Mockito.mock(QueryResponse.class);
        SolrDocumentList resultList = new SolrDocumentList();
        resultList.setNumFound(10);
        Mockito.when(responseMock.getResults()).thenReturn(resultList);
        Mockito.when(solrServerMock.query(Mockito.any(SolrQuery.class))).thenReturn(responseMock);

        long result = solrTemplate.count(new SimpleQuery(new Criteria("field_1").is("value1")));
        Assert.assertEquals(resultList.getNumFound(), result);

        Mockito.verify(solrServerMock, Mockito.times(1)).query(captor.capture());

        Assert.assertEquals(Integer.valueOf(0), captor.getValue().getStart());
        Assert.assertEquals(Integer.valueOf(0), captor.getValue().getRows());
    }

    @Test
    public void testCountWhenPagingSet() throws SolrServerException {
        ArgumentCaptor<SolrQuery> captor = ArgumentCaptor.forClass(SolrQuery.class);
        QueryResponse responseMock = Mockito.mock(QueryResponse.class);
        SolrDocumentList resultList = new SolrDocumentList();
        resultList.setNumFound(10);
        Mockito.when(responseMock.getResults()).thenReturn(resultList);
        Mockito.when(solrServerMock.query(Mockito.any(SolrQuery.class))).thenReturn(responseMock);

        Query query = new SimpleQuery(new Criteria("field_1").is("value1"));
        query.setPageRequest(new PageRequest(0, 5));
        long result = solrTemplate.count(query);
        Assert.assertEquals(resultList.getNumFound(), result);

        Mockito.verify(solrServerMock, Mockito.times(1)).query(captor.capture());

        Assert.assertEquals(Integer.valueOf(0), captor.getValue().getStart());
        Assert.assertEquals(Integer.valueOf(0), captor.getValue().getRows());
    }

    @Test(expected = IllegalArgumentException.class)
    public void testCountNullQuery() {
        solrTemplate.count(null);
    }

    @Test
    public void testCommit() throws SolrServerException, IOException {
        solrTemplate.commit();
        Mockito.verify(solrServerMock, Mockito.times(1)).commit();
    }

    @Test
    public void testSoftCommit() throws SolrServerException, IOException {
        solrTemplate.softCommit();
        Mockito.verify(solrServerMock, Mockito.times(1)).commit(Matchers.eq(true), Matchers.eq(true),
                Matchers.eq(true));
    }

    @Test
    public void testRollback() throws SolrServerException, IOException {
        solrTemplate.rollback();
        Mockito.verify(solrServerMock, Mockito.times(1)).rollback();
    }

    @Test
    public void testDifferentQueryParser() throws SolrServerException {
        QueryParser parser = new QueryParser() {

            @Override
            public void registerConverter(Converter<?, ?> converter) {
            }

            @Override
            public String getQueryString(SolrDataQuery query) {
                return "*:*";
            }

            @Override
            public SolrQuery constructSolrQuery(SolrDataQuery query) {
                return new SolrQuery(getQueryString(query));
            }

        };

        solrTemplate.registerQueryParser(SimpleQuery.class, parser);
        solrTemplate.query(new SimpleQuery(new SimpleStringCriteria("my:criteria")), null);

        ArgumentCaptor<SolrParams> captor = ArgumentCaptor.forClass(SolrParams.class);

        Mockito.verify(solrServerMock, Mockito.times(1)).query(captor.capture());
        Assert.assertEquals("*:*", captor.getValue().getParams(CommonParams.Q)[0]);
    }

    /**
     * @see DATASOLR-88
     */
    @Test
    public void testSaveBoostedShouldUseDocumentBoost()
            throws IOException, SolrServerException, SecurityException, NoSuchFieldException {

        solrTemplate.saveBean(SIMPLE_BOOSTED_OBJECT);

        ArgumentCaptor<SolrInputDocument> captor = ArgumentCaptor.forClass(SolrInputDocument.class);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(captor.capture(), Mockito.eq(-1));

        Assert.assertEquals(SIMPLE_BOOSTED_OBJECT.getId(), captor.getValue().getFieldValue("id"));
        Assert.assertEquals(SIMPLE_BOOSTED_OBJECT.getValue(), captor.getValue().getFieldValue("value"));

        float entityBoost = AnnotationUtils.getAnnotation(SIMPLE_BOOSTED_OBJECT.getClass(), SolrDocument.class)
                .boost();
        Assert.assertThat(captor.getValue().getDocumentBoost(), Is.is(entityBoost));
    }

    /**
     * @see DATASOLR-88
     */
    @Test
    public void testSaveBoostedShouldUseFieldBoostViaIndexedAnnotation()
            throws IOException, SolrServerException, SecurityException, NoSuchFieldException {

        solrTemplate.saveBean(SIMPLE_BOOSTED_OBJECT);

        ArgumentCaptor<SolrInputDocument> captor = ArgumentCaptor.forClass(SolrInputDocument.class);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(captor.capture(), Mockito.eq(-1));

        Assert.assertEquals(SIMPLE_BOOSTED_OBJECT.getId(), captor.getValue().getFieldValue("id"));
        Assert.assertEquals(SIMPLE_BOOSTED_OBJECT.getValue(), captor.getValue().getFieldValue("value"));

        float fieldBoost = AnnotationUtils
                .getAnnotation(SIMPLE_BOOSTED_OBJECT.getClass().getDeclaredField("boostedField"), Indexed.class)
                .boost();
        Assert.assertThat(captor.getValue().getField("boostedField").getBoost(), Is.is(fieldBoost));
    }

    /**
     * @throws IOException
     * @throws SolrServerException
     * @see DATASOLR-72
     */
    @Test
    public void schemaShouldBeUpdatedPriorToSavingEntity() throws SolrServerException, IOException {

        NamedList<Object> nl = new NamedList<Object>();
        nl.add("json", "{ \"schema\" : {\"name\" : \"core1\" }, \"version\" : 1.5 }");
        Mockito.when(solrServerMock.request(Mockito.any(SolrSchemaRequest.class))).thenReturn(nl);
        Mockito.when(solrServerMock.request(Mockito.any(SolrSchemaRequest.class))).thenReturn(nl);

        solrTemplate = new SolrTemplate(solrServerMock, "core1");
        solrTemplate.setSchemaCreationFeatures(Collections.singletonList(Feature.CREATE_MISSING_FIELDS));
        solrTemplate.afterPropertiesSet();
        solrTemplate.saveBean(new DocumentWithIndexAnnotations());

        ArgumentCaptor<SolrRequest> requestCaptor = ArgumentCaptor.forClass(SolrRequest.class);
        Mockito.verify(solrServerMock, Mockito.times(3)).request(requestCaptor.capture());

        SolrRequest capturedRequest = requestCaptor.getValue();

        Assert.assertThat(capturedRequest.getMethod(), IsEqual.equalTo(SolrRequest.METHOD.POST));
        Assert.assertThat(capturedRequest.getPath(), IsEqual.equalTo("/schema/fields"));
        Assert.assertThat(capturedRequest.getContentStreams(), IsNull.notNullValue());
    }

    /**
     * @see DATASOLR-83
     */
    @Test
    public void testGetById() throws SolrServerException, IOException {

        ArgumentCaptor<SolrRequest> captor = ArgumentCaptor.forClass(SolrRequest.class);
        QueryResponse responseMock = Mockito.mock(QueryResponse.class);
        SolrDocumentList resultList = new SolrDocumentList();
        Mockito.when(responseMock.getResults()).thenReturn(resultList);
        Mockito.when(solrServerMock.request(captor.capture())).thenReturn(new NamedList<Object>());

        DocumentWithIndexAnnotations result = solrTemplate.getById("myId", DocumentWithIndexAnnotations.class);

        Mockito.verify(solrServerMock, Mockito.times(1)).request(captor.capture());
        Assert.assertNull(result);
        Assert.assertEquals("myId", captor.getValue().getParams().get("ids"));
        Assert.assertEquals("/get", captor.getValue().getPath());
    }

    /**
     * @see DATASOLR-83
     */
    @Test
    public void testGetByIds() throws SolrServerException, IOException {

        ArgumentCaptor<SolrRequest> captor = ArgumentCaptor.forClass(SolrRequest.class);

        QueryResponse responseMock = Mockito.mock(QueryResponse.class);
        SolrDocumentList resultList = new SolrDocumentList();
        Mockito.when(responseMock.getResults()).thenReturn(resultList);
        Mockito.when(solrServerMock.request(captor.capture())).thenReturn(new NamedList<Object>());

        List<String> ids = Arrays.asList("myId1", "myId2");
        Collection<DocumentWithIndexAnnotations> result = solrTemplate.getById(ids,
                DocumentWithIndexAnnotations.class);

        Mockito.verify(solrServerMock, Mockito.times(1)).request(captor.capture());
        Assert.assertTrue(result.isEmpty());
        Assert.assertArrayEquals(new String[] { "myId1", "myId2" }, captor.getValue().getParams().getParams("ids"));
        Assert.assertEquals("/get", captor.getValue().getPath());
    }

    /**
     * @see DATASOLR-160
     */
    @Test
    public void testSaveShouldNotSaveScoreField()
            throws IOException, SolrServerException, SecurityException, NoSuchFieldException {

        solrTemplate.saveBean(new DocumentWithScoreAnnotation());

        ArgumentCaptor<SolrInputDocument> captor = ArgumentCaptor.forClass(SolrInputDocument.class);
        Mockito.verify(solrServerMock, Mockito.times(1)).add(captor.capture(), Mockito.eq(-1));

        Assert.assertNull(captor.getValue().getFieldValue("score"));
    }

    static class DocumentWithIndexAnnotations {

        @Id
        String id;
        @Indexed(name = "namedProperty")
        String renamedProperty;
    }

    static class DocumentWithScoreAnnotation {

        @Id
        String id;
        @Score
        Float scoreProperty;
    }

}