Program termination during quartz scheduler verification using power mockito - unit-testing

I am trying to verify the quartz scheduler process by mocking System.currentTimeMillis() using PowerMockito .
Scenario :
I have scheduled a job for May 6th 2016 12 hrs .For verification I am trying to mock the System.currentTimeMillis() to scheduled time. So, the quartz will trigger on that particular time.
Test Case :
#RunWith(PowerMockRunner.class)
#PrepareForTest({ QuartzSchedulerThread.class })
public class SampleExampleTest {
#Test
public void test() {
/**
* mock the system.current milliseconds
*/
PowerMockito.mockStatic(System.class);
long value=getMockedMilliseconds();
PowerMockito.when(System.currentTimeMillis()).thenReturn(value);
System.out.println("Mocked milliseconds"+value);
try {
SchedulerFactory sf = new StdSchedulerFactory(getProperties());
Scheduler sched = sf.getScheduler();
sched.start();
} catch (SchedulerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public long getMockedMilliseconds() {
Date expectedDate=new Date(116, 4, 6 , 11, 57);
long mokedMilliSeconds = expectedDate.getTime();
return mokedMilliSeconds;
}
public Properties getProperties(){
Properties properties = new Properties();
properties.setProperty("org.quartz.scheduler.skipUpdateCheck", "true");
// set other properties ...such as
properties.setProperty("org.quartz.jobStore.class",
"org.quartz.impl.jdbcjobstore.JobStoreTX");
properties.setProperty("org.quartz.jobStore.driverDelegateClass",
"org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");
properties.setProperty("org.quartz.jobStore.tablePrefix", "QRTZ_");
properties.setProperty("org.quartz.jobStore.dataSource", "obulis");
//properties.setProperty("org.quartz.jobStore.misfireThreshold", "1000");
// Datasource configurations
properties.setProperty("org.quartz.dataSource.obulis.driver",
"org.postgresql.Driver");
properties.setProperty("org.quartz.dataSource.obulis.URL",
"jdbc:postgresql://192.168.27.43:5433/obulis");
properties.setProperty("org.quartz.dataSource.obulis.user", "postgres");
properties.setProperty("org.quartz.dataSource.obulis.password",
"Nuwaza123");
properties.setProperty("org.quartz.dataSource.obulis.maxConnections",
"5");
properties.setProperty("rg.quartz.dataSource.obulis.validationQuery",
"select 0");
properties.setProperty("org.quartz.threadPool.class",
"org.quartz.simpl.SimpleThreadPool");
properties.setProperty("org.quartz.threadPool.threadCount", "4");
return properties;
}
}
Problem:
While executing the test case the program terminates abruptly before starting the scheduler. If the PowerMock is removed it is starting the scheduler.
console:
Mocked milliseconds1462516020000
INFO [main] (MLog.java:80) - MLog clients using log4j logging.
INFO [main] (C3P0Registry.java:204) - Initializing c3p0-0.9.1.1 [built 15- March-2007 01:32:31; debug? true; trace: 10]
Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=true
What will be the cause of it? How to mock and verify whether the job will trigger on that particular time ?

I think you're going down a very bad way... You shouldn't mock the types you don't own: https://github.com/mockito/mockito/wiki/How-to-write-good-tests#dont-mock-type-you-dont-own .
What exactly do you want to verify? That Quartz is working? Makes no sense - if it didn't the library wouldn't be released ;) If you do want to plug it in in the integration test, just run a normal Quartz job. Let that job do sth (produce an output) and then check if this output is present.

Related

How to test predicate in an unit test?

I have an Apache Camel application, which uses a Choice with a Predicate. How can I test the predicate without an integration test?
Code
#SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
#Bean
public EndpointRouteBuilder route() {
return new EndpointRouteBuilder() {
#Override
public void configure() throws Exception {
from(file("d:/tmp/camel/"))
.choice()
.when(jsonpath("$[?(#.status == 0)]"))
.log("ok")
.otherwise()
.log("not ok");
}
};
}
}
Research
I read Test JUnit5, but it looks like an integration test. However, I don't want to test a full route.
I read Test Spring JUnit5, but it is an integration test.
Question
How can I extract the predicate jsonpath("$[?(#.status == 0)]") and test it isolated in an unit test with JUnit 5?
Might be hard to accomplish this without a CamelContext. I'd probably approach this with Camel's excellent mocking and stubbing utilities. But if you really just want to isolate the jsonpath expression, you could try something like this:
JsonPathExpression exp = new JsonPathExpression("$[?(#.status == 0)]");
Exchange exchange = new DefaultExchange(context);
final Predicate predicate = exp.createPredicate(context);
exchange.getIn().setBody("{ \"status\": 0 }");
final boolean matches = predicate.matches(exchange);
assertTrue(matches);
Note that you'll still need a CamelContext for this. Typically you'd get it by having the test class extend CamelTestSupport, or if you're in a spring environment, spring can autowire it: #Autowired CamelContext camelContext;
Edit: If you just want to test the JsonPath expression outside of Camel:
String jsonPath = "$[?(#.status == 0)]";
String json = "{ \"status\": 0 }";
DocumentContext jsonContext = JsonPath.parse(json);
JSONArray result = jsonContext.read(jsonPath);
assertEquals(1, result.size());
My opinion (you'll probably get 100 more ;-)
Separate that route into another class by itself that can be loaded into the Spring context later.
Use CamelTestSupport to load just Camel (not Spring) in JUnit.
Use Camel "advice" to change "from" to a direct, or create a file (in your test) to exercise the test case you want (once with each branch of the choice.
Again with "advice" change the log to mocks - then after running the file/message you want check to see if the correct mock got a message and the other did not.

Testing camel-sql route with in-memory database not fetching results

I have written the code using camel-sql which is working fine. Now I have to write test cases for the same. I have used in-memory database H2. I have initialized the database and assigned the datasource to sqlComponent.
// Setup code
#Override
protected JndiRegistry createRegistry() throws Exception {
JndiRegistry jndi = super.createRegistry();
// this is the database we create with some initial data for our unit test
database = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2).addScript("createTableAndInsert.sql").build();
jndi.bind("myDataSource", database);
return jndi;
}
// Testcase code
#SuppressWarnings("unchecked")
#Test
public void testRoute() throws Exception {
Exchange receivedExchange = template.send("direct:myRoute", ExchangePattern.InOut ,exchange -> {
exchange.getIn().setHeader("ID", new Integer(1));
});
camelContext.start();
MyClass updatedEntity = (MyClass)jdbcTemplate.queryForObject("select * from MY_TABLE where id=?", new Long[] { 1l } ,
new RouteTest.CustomerRowMapper() );
// Here I can get the updatedEntity from jdbcTemplate
assertNotNull(receivedExchange);
assertNotNull(updatedEntity);
}
// Main code
from("direct:myRoute")
.routeId("pollDbRoute")
.transacted()
.to("sql:select * from MY_TABLE msg where msg.id = :#"+ID+"?dataSource=#myDataSource&outputType=SelectOne&outputClass=com.entity.MyClass")
.log(LoggingLevel.INFO,"Polled message from DB");
The problem is, as soon as the test case starts, it is saying
No bean could be found in the registry for: myDataSource of type: javax.sql.DataSource
I looked into camel-SQL component test cases and doing the same thing but the code is not able to find dataSource. Please help. Thanks in advance.
After spending a lot of time on this issue, I identified that H2 database was using JDBCUtils to fetch records and It was throwing ClassNotFoundException. I was getting it nowhere in Camel exception hierarchy because this exception was being suppressed and all I was getting a generic exception message. Here is the exception:
ClassNotFoundException: com.vividsolutions.jts.geom.Geometry
After searching for the issue I found out that It requires one more dependency. So I added it and it resolved the issue.
Issue URL: https://github.com/elastic/elasticsearch/issues/9891
Dependency: https://mvnrepository.com/artifact/com.vividsolutions/jts-core/1.14.0

Integration testing with Akka-Camel

I started on a new akka project and having an issue with akka-camel integration testing..
So I have a consumer actor and am trying to test if it is receiving the message I send
Here is the test
#Test
public void testConsumer() {
final String testXml = "<user>" +
"<firstName>First</firstName>" +
"<lastName>Last</lastName>" +
"</user>";
new JavaTestKit(_system) {{
final JavaTestKit probe = new JavaTestKit(_system);
final ActorRef subject2 = _system.actorOf(Consumer.mkProps(probe.getRef(), endPoint, "testConsumerActor"));
camel.template().sendBody(endPoint, testXml);
}};
}
The test fails with the following exception
15:15:02.442 [Camel (test-cdr) thread #0 - seda://testRecords] WARN o.a.c.component.seda.SedaConsumer - Error processing exchange. Exchange[Message: <user><firstName>First</firstName><lastName>Last</lastName></user>]. Caused by: [akka.camel.ActorNotRegisteredException - Actor [akka://test-cdr/user/$a] doesn't exist]
akka.camel.ActorNotRegisteredException: Actor [akka://test-cdr/user/$a] doesn't exist
at akka.camel.internal.component.ActorProducer$$anonfun$actorFor$1.apply(ActorComponent.scala:182) ~[akka-camel_2.10-2.2.3.jar:na]
at akka.camel.internal.component.ActorProducer$$anonfun$actorFor$1.apply(ActorComponent.scala:182) ~[akka-camel_2.10-2.2.3.jar:na]
at scala.Option.getOrElse(Option.scala:120) ~[scala-library-2.10.3.jar:na]
at akka.camel.internal.component.ActorProducer.actorFor(ActorComponent.scala:182) ~[akka-camel_2.10-2.2.3.jar:na]
When I debug through my test, I notice that before the constructor for my consumer is called, camel is sending the message. How do I prevent this? or am I missing anything?
SD
I had issue with Akka-Camel which seemed to be problem with Camel initialization. I had to wait for Camel to initialize before I could send messages.
It's descibed in Akka Camel - JMS messages lost - should wait for initialization of Camel?
Java version for Camel initialization was:
ActorRef producer = system.actorOf(new Props(SimpleProducer.class), "simpleproducer");
Timeout timeout = new Timeout(Duration.create(15, SECONDS));
Future<ActorRef> activationFuture = camel.activationFutureFor(producer,timeout, system.dispatcher());
activationFuture.onComplete(new OnComplete<ActorRef>() {
#Override
public void onComplete(Throwable arg0, ActorRef arg1)
throws Throwable {
producer.tell("First!!");
}
},system.dispatcher());
Are you performing any sort of Camel initialization in your test? If not, adding something like this may help.

Workflow Services Testing and Moq

I'm trying to unit test a Workflow Service by using Microsoft.Activities.UnitTesting
The goal is to mock the service's extensions in order to ensure that all steps are executed.
The mock objects don't seem to get called even though the extensions are registered in the Host. As expected, if the extensions are not registered an exception is thrown.
WorkflowServiceTestHost host = null;
try
{
Mock<ISubscriber> publisher = new Mock<ISubscriber>();
Mock<IWebWorker> webWorker = new Mock<IWebWorker>();
var voucher = new Voucher();
using (host = new WorkflowServiceTestHost(workflowServiceFile, serviceAddress))
{
host.WorkflowExtensions.Add<ISubscriber>(() => publisher.Object);
host.WorkflowExtensions.Add<IWebWorker>(() => webWorker.Object);
host.Open();
using (var factory = new ChannelFactory<IServiceInterface>(clientBinding, serviceAddress))
{
var proxy = factory.CreateChannel() as IServiceInterface;
proxy.Process(voucher);
}
}
**//These validations fail...**
publisher.Verify(m => m.Push(It.IsAny<Voucher>()), Times.Once(), "ISubscriber.Push was not called.");
webWorker.Verify(m => m.Done(It.IsAny<Voucher>()), Times.Once(), "IWebWorker.Done was not called.");
// The host must be closed before asserting tracking
// Explicitly call host.Close or exit the using block to do this.
}
finally
{
if (host != null)
{
host.Tracking.Trace(TrackingOptions.All);
}
}
The workflow runs as expected in IIS.
Thanks!
Edit: This error is being written in the Workflow Host output:
WorkflowInstance "Sequential Service" Unhandled Exception Source "Receive Process Message"
Exception <System.NotSupportedException: Expression Activity type 'CSharpReference`1' requires compilation in order to run.
Please ensure that the workflow has been compiled.
at System.Activities.Expressions.CompiledExpressionInvoker.InvokeExpression(ActivityContext activityContext)
at Microsoft.CSharp.Activities.CSharpReference`1.Execute(CodeActivityContext context)
at System.Activities.CodeActivity`1.InternalExecuteInResolutionContext(CodeActivityContext context)
at System.Activities.Runtime.ActivityExecutor.ExecuteInResolutionContext[T](ActivityInstance parentInstance, Activity`1 expressionActivity)
at System.Activities.OutArgument`1.TryPopulateValue(LocationEnvironment targetEnvironment, ActivityInstance targetActivityInstance, ActivityExecutor executor)
at System.Activities.RuntimeArgument.TryPopulateValue(LocationEnvironment targetEnvironment, ActivityInstance targetActivityInstance, ActivityExecutor executor, Object argumentValueOverride, Location resultLocation, Boolean skipFastPath)
at System.Activities.ActivityInstance.InternalTryPopulateArgumentValueOrScheduleExpression(RuntimeArgument argument, Int32 nextArgumentIndex, ActivityExecutor executor, IDictionary`2 argumentValueOverrides, Location resultLocation, Boolean isDynamicUpdate)
at System.Activities.ActivityInstance.ResolveArguments(ActivityExecutor executor, IDictionary`2 argumentValueOverrides, Location resultLocation, Int32 startIndex)
at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)>
I've just realized WorkflowServiceTestHost is a Microsoft.Activities.UnitTesting class and not yours.
So, let's see if this is possible. As I saw on its source code you can pass to the constructor the WorkflowService's object itself instead of the XAMLX file. Something like this:
// Load WorkflowService from .xamlx
// Actually this is the method WorkflowserviceTestHost uses when you pass a
// .xamlx so we're taking a step back to be able to compile the body
var wfService = XamlServices.Load("c:\\workflowservice.xamlx") as WorkflowService;
// Compile workflow body
CompileExpressions(wfService.Body);
// Now you can use WorkflowServiceTestHost
using (host = new WorkflowServiceTestHost(wfService, serviceAddress))
{
// ... do your thing
}
CompileExpressions is taken from the link that I gave you earlier.
That being said, it seems odd consider testing a WCF service as unit-testing. Unit tests should be focused on small activities of your service, those are truly unit-testable. Integration tests (or functional tests) is where you test services with all its dependencies (IIS\WAS, network, DBs, etc).

JMS Testing - JMSTemplate send not executed

I have code piece sending jms messages via Spring JMSTemplate. For testing the the method i use Mockito.
My code looks like following.... publishDialogueServiceMessage()->
brokerUrl = jmsQueueProperties.getProperty(MessageRouterConstants.JMS_QUEUE_URL);
LOG.info("The broker url is : {}", brokerUrl);
jmsTemplate.send(jmsQueueProperties.getProperty(MessageRouterConstants.QUEUE), new MessageCreator() {
#Override
public Message createMessage(Session session) throws JMSException {
ObjectMessage obj = session.createObjectMessage(serviceResponse);
messageSent = true;
return obj;
}
});
In above code to i set boolean variable true, to check that if the message is sent
My Test looks following,
#Before
public void setUp() throws Exception {
connectionFactory = Mockito.spy(new ActiveMQConnectionFactory(
"vm://localhost?broker.persistent=false"));
conn = connectionFactory.createConnection();
conn.start();
}
#After
public void cleanUp() throws Exception{
conn.stop();
}
#Test
public void testPublishDialogueServiceMessage()
{
ServiceResponse response = Mockito.mock(
ServiceResponse.class, Mockito.withSettings()
.serializable());
JmsTemplate mockTemplate = Mockito.mock(JmsTemplate.class);
java.util.Properties p = Mockito.mock(java.util.Properties.class);
Mockito.when(p.getProperty(MessageRouterConstants.QUEUE))
.thenReturn("outbound.request.queue");
mockTemplate.setConnectionFactory(connectionFactory);
mockTemplate.setDeliveryPersistent(true);
mockTemplate.setSessionAcknowledgeMode(2);
mockTemplate.setSessionTransacted(true);
ReflectionTestUtils.setField(publisher, "jmsQueueProperties", p);
ReflectionTestUtils.setField(publisher, "jmsTemplate", mockTemplate);
// test
publisher.publishDialogueServiceMessage(response);
ArgumentCaptor<MessageCreator> msgCreator = ArgumentCaptor.forClass(MessageCreator.class);
Mockito.verify(p, Mockito.times(2))
.getProperty(Mockito.anyString());
Mockito.verify(mockTemplate, Mockito.times(1)).send(
Mockito.anyString(), Mockito.any(MessageCreator.class));
//MessageCreator msgCrt = Mockito.spy(msgCreator.getValue());
//Assert.notNull(msgCrt);
Assert.isTrue(publisher.isMessageSent());
}
In test i facing an interesting problem as publisher.isMessageSent() always returns me FALSE indicating that send message seems not executed(?). but Mockito.verify(mockTemplate, Mockito.times(1)).send(Mockito.anyString(), Mockito.any(MessageCreator.class)); goes fine.
I am wondering what is the cause that my messageSent variable not setting. Can anyone shed some light what I might be doing wrong.
Simple, you have a mock for the jmsTemplate (your mockTemplate). When a method is invoked on a mock it doesn't do anything other than record the call to the mock. So the mock doesn't know that it should attempt to invoke the msgCreator.
Looking at your test I see some obvious issues that suggest a lack of knowledge of Mockito. Why are you setting all of those fields on mockTemplate? It is a mock, it will not use those fields anyway. This also suggests that you don't need the code in your #Before and #After.
If you REALLY want your test to send a message via JMS (and thereby invoke the message createor) you should use a spy on JmsTemplate instead of a mock. However, I would highly discourage this as your test will be dependent on an external system and you would in effect be testing JsmTemplate. The fact that your mock gets invoked properly is sufficient. The only additional thing I think you need to do is to invoke the message creator being passed to the mock to verify that it creates the message correctly.