Tests pass with Playframework 1.2.x but fails with Playframework 1.4.x - playframework-1.x

I am migrating my application from Play1.2+Java7 to Play1.4+Java8
Play1.2+Java7 my test passes OK
Play1.4+Java8 my test fails.
I have reduced the code to the minimum and reproduced the problem. Here is the main line
The model is
package models;
import play.db.jpa.Model;
import javax.persistence.Entity;
#Entity
public class Token extends Model {
public String name;
public String role;
}
The controller is
package controllers;
import models.Token;
import play.mvc.Controller;
public class Application extends Controller {
public static void index() {
renderJSON(Token.all().fetch());
}
}
The DB test configuration is
%test.application.mode=dev
%test.db.url=jdbc:h2:mem:play;MODE=MYSQL;LOCK_MODE=0
%test.jpa.ddl=create
The test is
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.junit.*;
import org.junit.Before;
import play.test.*;
import play.mvc.*;
import play.mvc.Http.*;
import models.*;
public class ApplicationTest extends FunctionalTest {
#Before
public void before() {
Token.deleteAll();
}
#Test
public void testThatIndexPageWorks() {
{
Response response = GET("/");
assertIsOk(response);
String content = getContent(response);
System.out.println(content);
assertFalse(content.contains("le nom"));
assertFalse(content.contains("identifier"));
}
Token t = new Token();
t.name="le nom";
t.role="identifier";
t.save();
{
Response response = GET("/");
assertIsOk(response);
String content = getContent(response);
System.out.println(content);
assertTrue(content.contains("le nom"));
assertTrue(content.contains("identifier"));
}
}
}
The behaviour is not predictable. It seems that saving entities in the tests are committed async and calling the controller depends on the threads while it did not in release 1.2
I can provide the whole project if necessary

As I do not want to use the fixtures, I have to manually sync the DB: test call of model.save() is done within a local transaction. The transaction is not closed when GET is called. the data is not flushed yet.
I thought that it was covered by
jpa FlushModeType COMMIT
It seems that it is the case in 1.2.x, but not the case in 1.4.x
I modified the test adding the code snippet below after save() and deleteAll(), and it works fine
if ( play.db.jpa.JPA.em().getTransaction().isActive()) {
play.db.jpa.JPA.em().getTransaction().commit();
play.db.jpa.JPA.em().getTransaction().begin();
}

Related

JMockit can't find EJB, get NoSuchMethodException instead

Trying to mock a MessageDriven bean but have trouble getting the #EJB to be injected. The #Resource works "fine" (doesn't break it at least).
If I comment out the #EJB line in MyMDB it works fine. Probably an easy thing I missed, but I can't find it...
Also I found that replacing #EJB with #Inject will make it work, but I want to know why it doesn't work with #EJB since we have a lot of code like that.
Using JDK7 and JMockit v1.39
The error I get is:
java.lang.RuntimeException: java.lang.NoSuchMethodException: com.sun.proxy.$Proxy7.lookup()
Caused by: java.lang.NoSuchMethodException: com.sun.proxy.$Proxy7.lookup()
at java.lang.Class.getMethod(Class.java:1678)
MyMDB.java:
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJB;
import javax.ejb.MessageDriven;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageListener;
#MessageDriven(activationConfig = {
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(propertyName = "destination", propertyValue = "/queue/myqueue") })
public class MyMDB implements MessageListener {
#Resource(mappedName = "java:/JmsBT")
ConnectionFactory connectionFactory;
#EJB
ParConfigI parConfig;
#Override
public void onMessage(Message message) {
System.out.println("onMessage called");
}
}
MyMDBTest.java
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import org.junit.Test;
import mockit.Injectable;
import mockit.Mocked;
import mockit.Tested;
public class MyMDBTest {
#Tested
MyMDB sut;
#Injectable
ConnectionFactory jmsbt;
#Injectable
ParConfigI parConfigI;
#Mocked
Message mockedMessage;
#Test
public void testSmall() {
sut.onMessage(mockedMessage);
}
}
ParConfigI.java
import javax.ejb.Local;
#Local
public interface ParConfigI {
public void testmethod();
}
The problem is that JMockit attempts to read the lookup attribute on the #EJB annotation, but this attribute only exists in EJB 3.1+ (added in Java EE 6), not in EJB 3.0 (Java EE 5). Hence the NoSuchMethodException.
JMockit 1.40 is fixing this, but Java EE 6 has been available since early 2010. So, upgrading from the ancient Java EE 5 would also solve the problem.

How to write Elastic unit tests to test query building

I want to write unit tests that test the Elastic query building. I want to test that certain param values produce certain queries.
I started looking into ESTestCase. I see that you can mock a client using ESTestCase. I don't really need to mock the ES node, I just need to reproduce the query building part, but that requires the client.
Has anybody dealt with such issue?
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.ESTestCase;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import com.google.common.collect.Lists;
public class SearchRequestBuilderTests extends ESTestCase {
private static Client client;
#BeforeClass
public static void initClient() {
//this client will not be hit by any request, but it needs to be a non null proper client
//that is why we create it but we don't add any transport address to it
Settings settings = Settings.builder()
.put("", createTempDir().toString())
.build();
client = TransportClient.builder().settings(settings).build();
}
#AfterClass
public static void closeClient() {
client.close();
client = null;
}
public static Map<String, String> createSampleSearchParams() {
Map<String, String> searchParams = new HashMap<>();
searchParams.put(SenseneConstants.ADC_PARAM, "US");
searchParams.put(SenseneConstants.FETCH_SIZE_QUERY_PARAM, "10");
searchParams.put(SenseneConstants.QUERY_PARAM, "some query");
searchParams.put(SenseneConstants.LOCATION_QUERY_PARAM, "");
searchParams.put(SenseneConstants.RADIUS_QUERY_PARAM, "20");
searchParams.put(SenseneConstants.DISTANCE_UNIT_PARAM, DistanceUnit.MILES.name());
searchParams.put(SenseneConstants.GEO_DISTANCE_PARAM, "true");
return searchParams;
}
#Test
public void test() {
BasicSearcher searcher = new BasicSearcher(client); // this is my application's searcher
Map<String, String> searchParams = createSampleSearchParams();
ArrayList<String> filterQueries = Lists.newArrayList();
SearchRequest searchRequest = SearchRequest.create(searchParams, filterQueries);
MySearchRequestBuilder medleyReqBuilder = new MySearchRequestBuilder.Builder(client, "my_index", searchRequest).build();
SearchRequestBuilder searchRequestBuilder = medleyReqBuilder.constructSearchRequestBuilder();
System.out.print(searchRequestBuilder.toString());
// Here I want to assert that the search request builder output is what it should be for the above client params
}
}
I get this, and nothing in the code runs:
Assertions mismatch: -ea was not specified but -Dtests.asserts=true
REPRODUCE WITH: mvn test -Pdev -Dtests.seed=5F09BEDD71BBD14E - Dtests.class=SearchRequestBuilderTests -Dtests.locale=en_US -Dtests.timezone=America/Los_Angeles
NOTE: test params are: codec=null, sim=null, locale=null, timezone=(null)
NOTE: Mac OS X 10.10.5 x86_64/Oracle Corporation 1.7.0_80 (64-bit)/cpus=4,threads=1,free=122894936,total=128974848
NOTE: All tests run in this JVM: [SearchRequestBuilderTests]
Obviously a bit late but...
So this actually has nothing to do with the ES Testing framework but rather your run settings. Assuming you are running this in eclipse, this is actually a duplicate of Assertions mismatch: -ea was not specified but -Dtests.asserts=true.
eclipse preference -> junit -> Add -ea checkbox enable.
right click on the eclipse project -> run as -> run configure -> arguments tab -> add the -ea option in vm arguments

Make Logback throw exception on ERROR level log events

When running unit tests, I'd like to fail any tests during which ERROR level message is logged. What would be the easiest way to achieve this using SLF4J/Logback? I'd like to avoid writing my own ILoggerFactory implementation.
I tried writing a custom Appender, but I cannot propagate exceptions through the code that's calling the Appender, all exceptions from Appender get caught there.
The key is to write a custom appender. You don't say which unit testing framework you use, but for JUnit I needed to do something similar (it was a little more complex than just all errors, but basically the same concept), and created a JUnit #Rule that added my appender, and the appender fails the test as needed.
I place my code for this answer in the public domain:
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import org.junit.rules.ExternalResource;
import org.slf4j.LoggerFactory;
import static org.junit.Assert.fail;
/**
* A JUnit {#link org.junit.Rule} which attaches itself to Logback, and fails the test if an error is logged.
* Designed for use in some tests, as if the system would log an error, that indicates that something
* went wrong, even though the error was correctly caught and logged.
*/
public class FailOnErrorLogged extends ExternalResource {
private FailOnErrorAppender appender;
#Override
protected void before() throws Throwable {
super.before();
final LoggerContext loggerContext = (LoggerContext)(LoggerFactory.getILoggerFactory());
final Logger rootLogger = (Logger)(LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME));
appender = new FailOnErrorAppender();
appender.setContext(loggerContext);
appender.start();
rootLogger.addAppender(appender);
}
#Override
protected void after() {
appender.stop();
final Logger rootLogger = (Logger)(LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME));
rootLogger.detachAppender(appender);
super.after();
}
private static class FailOnErrorAppender extends AppenderBase<ILoggingEvent> {
#Override
protected void append(final ILoggingEvent eventObject) {
if (eventObject.getLevel().isGreaterOrEqual(Level.ERROR)) {
fail("Error logged: " + eventObject.getFormattedMessage());
}
}
}
}
An example of usage:
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ExampleTest {
private static final Logger log = LoggerFactory.getLogger(ExampleTest.class);
#Rule
public FailOnErrorLogged failOnErrorLogged = new FailOnErrorLogged();
#Test
public void testError() {
log.error("Test Error");
}
#Test
public void testInfo() {
log.info("Test Info");
}
}
The testError method fails and the testInfo method passes. It works the same if the test calls the real class-under-test that logs an error as well.
Logging frameworks are generally designed not to throw any exceptions to the user. Another option (in addition to Raedwald's answer) would be to create a custom appender that sets a static boolean flag to true when an ERROR message is logged, reset this flag in a setup method and check it in a teardown method (or create a JUnit rule to reset/check the flag).
So, you want to fail your test case if any error reporting message of the logger is called.
Use dependency injection to associate the code to be tested with the logger it should use.
Implement a test double that implements the SLF4J logger interface, and which does nothing for most methods, but throws an AssertionError for the error logging methods.
In the set-up part of the test case, inject the test double.

Grails Unit Test

I have unit test wich extends GrailsUnitTestCase :
import grails.test.GrailsUnitTestCase
class HttpdParserSpec extends GrailsUnitTestCase {
}
However I saw in Grails documentation that is deprecated.
I tried to use the following :
import grails.test.mixin.TestFor
#TestFor(HttpdParser)
class HttpdParserSpec {
}
I obtain the following error :
Cannot add Domain class [class fr.edu.toolprod.parser.HttpdParser]. It
is not a Domain!
It's true.It's not a Domain class.I only want test a simple class HttpdParser.
What am I doing wrong ?
So how to make a simple unit test ? Have you an example ?
Don't use the TestFor annotation. Just write a unit test as you normally would. TestFor is useful for rigging up Grails artifacts and relevant elements of the environment for unit testing them.
class HttpdParserSpec extends spock.lang.Specification {
void 'test something'() {
when:
def p = new HttpdParser()
p.doSomething()
then:
p.someValue == 42
}
}
You can also just use the #TestMixin annotation with the GrailsUnitTestCaseMixin like this:
import grails.test.mixin.support.GrailsUnitTestMixin
import grails.test.mixin.TestMixin
#TestMixin(GrailsUnitTestMixin)
class MyTestClass {}

Testing Solr via Embedded Server

I'm coding some tests for my solr-indexer application. Following testing best practices, I want to write code self-dependant, just loading the schema.xml and solrconfig.xml and creating a temporary data tree for the indexing-searching tests.
As the application is most written in java, I'm dealing with SolrJ library, but I'm getting problems (well, I'm lost in the universe of corecontainers-coredescriptor-coreconfig-solrcore ...)
Anyone can place here some code to create an Embedded Server that loads the config and also writes to a parameter-pased data-dir?
You can start with the SolrExampleTests which extends SolrExampleTestBase which extends AbstractSolrTestCase .
Also this SampleTest.
Also take a look at this and this threads.
This is an example for a simple test case. solr is the directory that contains your solr configuration files:
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"));
}
}
See this blogpost for more info:Solr Integration Tests
First you need to set your Solr Home Directory which contains solr.xml and conf folder containing solrconfig.xml, schema.xml etc.
After that you can use this simple and basic code for Solrj.
File solrHome = new File("Your/Solr/Home/Dir/");
File configFile = new File(solrHome, "solr.xml");
CoreContainer coreContainer = new CoreContainer(solrHome.toString(), configFile);
SolrServer solrServer = new EmbeddedSolrServer(coreContainer, "Your-Core-Name-in-solr.xml");
SolrQuery query = new SolrQuery("Your Solr Query");
QueryResponse rsp = solrServer.query(query);
SolrDocumentList docs = rsp.getResults();
Iterator<SolrDocument> i = docs.iterator();
while (i.hasNext()) {
System.out.println(i.next().toString());
}
I hope this helps.