3

I'm trying to write a test case that checks whether a document was pushed into the SOLR index. The problem is, the assertion is failing because the transaction hasn't been committed. The database assertions are fine, they respond with the right rowcounts before the rollback. But I'm getting 0 count on the documents in SOLR, I presume because when I query the index, the previous document wouldn't have been committed into the index yet.

All conditions pass in this test, except the last one, which returns 0 count.

Can anyone suggest how I can implement this test to take into account transaction boundary management with SOLR and rollback requirements?

@Test
@Sql(scripts = {"classpath:test/sql/customers/delete_customer.sql"})
@Rollback
public void testSubmitSubscriberRegistration() throws Exception{
    logger.entry();
    final String email="Billy.Evans@mailinator.com";
    int orig = JdbcTestUtils.countRowsInTable(jdbcTemplate, "customers");
    MvcResult result = this.mockMvc.perform(post("/ajax/customers/register")
                    .param("firstName", "Bill")
                    .param("lastName", "Evans")
                    .param("preferredName", "Billy")
                    .param("email", email)
                    .param("subscriber", "true")
    )
            .andExpect(status().isOk())
            .andExpect(MockMvcResultMatchers.jsonPath("$.object.id", Matchers.notNullValue()))
                    .andReturn();
    logger.debug(result.getResponse().getContentAsString());

    Assert.assertEquals(JdbcTestUtils.countRowsInTable(jdbcTemplate, "customers"), orig+1);
    Assert.assertEquals(JdbcTestUtils.countRowsInTable(jdbcTemplate, "customer_roles"), orig+1);
    Mockito.verify(mockCustomerNotifier, Mockito.times(1)).sendRegistrationConfirmation(Mockito.any(Customer.class), Mockito.anyString());

    // now we do a quick confirmation of the state of the user.
    Customer customer = customerAccountService.findByEmail(email);
    Assert.assertNotNull(customer);
    Assert.assertTrue(customer.isSubscriber());
    Assert.assertEquals(customer.getFirstName(), "Bill");
    Assert.assertEquals(customer.getLastName(), "Evans");
    Assert.assertEquals(customer.getEmail(), email);
    boolean found = false;
    for (Role role: customer.getRoles())
    {
        if (role.getCode().equals("REGISTERED_CUSTOMER")){
            found = true;
        }
    }

    Assert.assertTrue(found);

    // now we have to verify the search indexes were updated with the customer details.
    Assert.assertNotNull(customerDocumentRepository);
    List<CustomerDocument> customerDocuments = customerDocumentRepository.findByEmail(email);
    Assert.assertEquals(1, customerDocuments.size());

}
Richard G
  • 5,243
  • 11
  • 53
  • 95

2 Answers2

1

Solr has a feature names RealTimeGet, this could be used to retrieve documents that are already sent to solr but still not committed.

Spring-Data-Solr present this feature as documented in RealTime Get section. With this feature you could retrieve the document based on its id even before transaction is committed.

Example:

CustomerDocument consumerDocument = solrTemplate.getById(email, CustomerDocument.class);
Assert.assertNotNull(consumerDocument);
Francisco Spaeth
  • 23,493
  • 7
  • 67
  • 106
  • Ok thanks Francisco, I will try this later today, it sounds like it will work. I just need to move some things around because email isn't actually the docId. thanks I'll come back to this. – Richard G Sep 16 '15 at 00:56
  • @Francisco I can't update my solr dependencies (currently using 1.2.0), is there a way to commit the transaction, just like we do `entityManager.flush()` for JPA transactions ? – coding_idiot Jan 18 '16 at 08:54
0

Below should commit the solr-transaction and then you can query Solr

solrTemplate.commit();

A sample code would look like :

@Test
public void testSomething(){
  createMyBeanAndSaveIt();

  solrTemplate.commit();

  solrTemplate.query...
}

For others stumbling upon this issue, above is what we did.

coding_idiot
  • 13,526
  • 10
  • 65
  • 116