I wonder if there is any best practice for junit testing of Solr 3.6. I want to automate testing of the Solr schema. Earlier posts mentioned the EmbeddedSolrServer. This class seems to have been abandoned from any version between 1.4 an 3.6. I use Spring 3.0.x and Maven for the project.
The options I considered are:
- writing a Junit Test Runner
- put the jetty startup code in the @Before or @BeforeClass method
- start a solr server in maven (probably not a good option)
- put some code in the spring test-context
I've used something similar to what's on this page to run these kinds of tests, all done with EmbeddedSolrServer on Solr 3.4.0. This is a simple approach, but if you want to automate Solr schema testing, it could be enough and isn't hard to implement.
It basically boils down to:
Adding references to junit
, solr-core
, slf4j-simple
and servlet-api
to your pom.xml
:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<type>jar</type>
<scope>test</scope>
</dependency>
<!-- dependencies needed for Solr integration test-->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-core</artifactId>
<version>1.4.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>test</scope>
</dependency>
And as an example test case, he adds this:
import java.io.IOException;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.util.AbstractSolrTestCase;
import org.apache.solr.client.solrj.SolrQuery;
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.common.SolrInputDocument;
import org.apache.solr.common.params.SolrParams;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class SolrSearchConfigTest extends AbstractSolrTestCase {
private SolrServer server;
@Override
public String getSchemaFile() {
return "solr/conf/schema.xml";
}
@Override
public String getSolrConfigFile() {
return "solr/conf/solrconfig.xml";
}
@Before
@Override
public void setUp() throws Exception {
super.setUp();
server = new EmbeddedSolrServer(h.getCoreContainer(), h.getCore().getName());
}
@Test
public void testThatNoResultsAreReturned() throws SolrServerException {
SolrParams params = new SolrQuery("text that is not found");
QueryResponse response = server.query(params);
assertEquals(0L, response.getResults().getNumFound());
}
@Test
public void testThatDocumentIsFound() throws SolrServerException, IOException {
SolrInputDocument document = new SolrInputDocument();
document.addField("id", "1");
document.addField("name", "my name");
server.add(document);
server.commit();
SolrParams params = new SolrQuery("name");
QueryResponse response = server.query(params);
assertEquals(1L, response.getResults().getNumFound());
assertEquals("1", response.getResults().get(0).get("id"));
}
}
edit: I haven't used Solr in quite a while, but I think this could still be a good starting point.
This is my take on it. It doesn't extend AbstractSolrTestCase, just a regular test class.
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.core.CoreContainer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class EmbeddedSolrServerTest {
private static final int SUCCESS = 0;
private final String indexLocation = "tomcat7/apps/apache-solr-3.6.0";
private EmbeddedSolrServer server;
@Before
public void setUp() throws Exception {
System.setProperty("solr.solr.home", indexLocation);
CoreContainer coreContainer = new CoreContainer.Initializer().initialize();
server = new EmbeddedSolrServer(coreContainer, "collection1");
}
@After
public void tearDown() throws Exception {
server.shutdown();
removeIndexDirectory();
}
@Test
public void testSolrSchema01() throws Exception {
SolrInputDocument doc1 = new SolrInputDocument();
doc1.addField("id", "123");
doc1.addField("something_txt", "super wombat");
UpdateResponse ur = server.add(doc1);
assertThat(ur.getStatus(), is(SUCCESS));
server.commit();
QueryResponse response1 = server.query(new SolrQuery("*:*"));
assertThat(response1.getResults().getNumFound(), is(1L));
QueryResponse response2 = server.query(new SolrQuery("something_txt:*wombat*"));
assertThat(response2.getResults().getNumFound(), is(1L));
}
private void removeIndexDirectory() throws IOException {
File indexDir = new File(indexLocation, "data/index");
FileUtils.deleteDirectory(indexDir);
}
}
My POM has the following dependencies:
<properties>
<solr.version>3.6.0</solr.version>
<httpcomponents.version>4.3.2</httpcomponents.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>${solr.version}</version>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-core</artifactId>
<version>${solr.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpcomponents.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>${httpcomponents.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
I've set up a separate project to keep all my Solr config in and run tests against it. The directory structure is:
solr-test
|--src
| |--test
|--tomcat7
` |--apps
|--apache-solr-3.6.0
|--conf
|--data
|--index
This seems to work well for me. This set up will also let you write tests using HttpSolrServer to test a remote server's schema.
Also, note the server.commit()
call in the middle of the test. This needs to be there otherwise the Solr transaction isn't complete and the new document won't be visible.
I'm using https://github.com/moliware/travis-solr for my tests, maybe it's useful for you too.