How to import Java static method into Drools file? - java

The java class and static method code is:
public class DroolsStringUtils {
public static boolean isEmpty(String param) {
if (param == null || "".equals(param)) {
return true;
}
return false;
}
}
The drl code is:
package com.rules
import com.secbro.drools.utils.DroolsStringUtils.isEmpty;
rule CheckIsEmpty
when
isEmpty("");
then
System.out.println("the param is not empty");
end
But the IDEA hints:
"cannot relove" on the method 'isEmpty("")'.
I just want to import a static method from java class to drl file.

Use import static to import a static method.
import static com.secbro.drools.utils.DroolsStringUtils.isEmpty;
// ^^^^^^
(edited:) and of course you cannot call a static method where a pattern is required:
rule CheckIsEmpty
when
eval( isEmpty("") )
then
System.out.println("the param is not empty");
end
(It helps considerably to read the Drools documentation.)

[this might have details only relevant for Drools 6.0 & earlier (thanks Roddy of the Frozen Peas)]
Looks like you could import the static method, as a function into Drools...
import function com.secbro.drools.utils.DroolsStringUtils.isEmpty
...and then be able to use your rule as you wrote it originally in your Question.
It seems [classic Java-style] static imports are not supported in
Drools
But it seems they can be imported with Drools function import
style
FWIW: To reference static fields - import the class with the static fields as normal import (not static or function), and then refer to static field with static reference:
import your.package.with.static.field.YourClass
...
YourClass.STATIC_FIELD
(That also works for static methods too, if you don't want to import them as function).

Related

Java import wildcard accessibility for nested static classes

How does the java accessibility (or perhaps, scope) work with respect to type import multi-level nested classes? An example:
ClassA.java:
package com.oracle.javatests;
public class ClassA {
public static class NestedAA {
public void printSomething() {
System.out.println("inside " + this.getClass().getName());
}
public static class NestedAB{
public void printSomethingAB() {
System.out.println("inside " + this.getClass().getName());
}
}
}
public void printSomething() {
System.out.println("inside " + this.getClass().getName());
}
}
Main.java
package com.oracle.javatests;
import com.oracle.javatests.ClassA.*;
// import com.oracle.javatests.ClassA.NestedAA.*; // Adding this will resolve NestedAB
public class Main {
public static void main (String[] args){
ClassA objA = new ClassA();
objA.printSomething();
NestedAA nestedAA = new NestedAA(); // Ok
NestedAB nestedAB = new NestedAB(); // Compiler error- NestedAB cannot be resolved to a type
}
}
The import statement does not import NestedAB type when using wildcards. A perhaps similar question led me to the java spec sheet which clarifies Type-Import-on-Demand Declarations :
A type-import-on-demand declaration allows all accessible types of a
named package or type to be imported as needed.
The accepted answer to the question implies that the on demand import declarations are not recursive. The reasoning is perhaps what Java considers "all accessible types of a named type", and the general concept of packages but I am falling short of connecting the dots and understand what accessible types means with respect to nested classes.
Can please anyone help explain how the type import and accessibility seem to work in java (while ignoring the arguable use of wildcard imports)
It's not heard to understand. import static com.foo.bar.*; is the exact same thing as import static com.foo.bar.[everything you can imagine here but without dots].
In other words, in your example, with import static pkg.ClassA.*; you can just write NestedAA without qualifiers and that works, because import static pkg.ClassA.NestedAA; would have made that work just the same.
You cannot write NestedAB unqualified and expect that to work; there is nothing you could possibly write instead of a * (which doesn't include dots) that would make that work, therefore, a star import doesn't make it work either.

PowerMockito VerifyStatic not working in 2.0.0-beta5

I am getting an issue using powermockito (2.0.0-beta5) to verify a static method was called a certain number of times when I call a different (also static) method. The classes are prepared for test at the top of my test file The relevant code snippet is:
mockStatic(Tester.class);
when(Tester.staticMethod(anyString(), anyString())).thenAnswer(new FirstResponseWithText());
OtherClass.methodThatCallsTesterStaticMethod("", "", "", false, "");
verifyStatic(Tester.class, times(3));
Tester.sendFaqRequest(anyString(), anyString());
FirstResponseWithText is a class that extends Answer that controls the order of responses. I've used that elsewhere and it works fine.
I get the following error on the verifyStatic line:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type Class and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
What is the proper way to pass the class to verifyStatic? All the examples I can find online are for pre-2.x.x releases where verifyStatic did not take a class parameter.
I think the PowerMockito version is not the problem. I tested the following code with versions
1.7.3,
2.0.0-beta.5 (your version),
2.0.2.
Application classes:
package de.scrum_master.stackoverflow.q52952222;
public class Tester {
public static String sendFaqRequest(String one, String two) {
return "real response";
}
}
package de.scrum_master.stackoverflow.q52952222;
public class OtherClass {
public static void methodThatCallsTesterStaticMethod(String one, String two, String three, boolean four, String five) {
System.out.println(Tester.sendFaqRequest("A", "B"));
System.out.println(Tester.sendFaqRequest("C", "D"));
System.out.println(Tester.sendFaqRequest("E", "F"));
}
}
Test classes:
package de.scrum_master.stackoverflow.q52952222;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.util.Arrays;
public class FirstResponseWithText implements Answer {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String methodName = invocation.getMethod().getName();
return methodName + " called with arguments: " + Arrays.toString(args);
}
}
package de.scrum_master.stackoverflow.q52952222;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.times;
import static org.powermock.api.mockito.PowerMockito.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Tester.class })
public class MyTest {
#Test
public void myTest() {
// Tell PowerMockito that we want to mock static methods in this class
mockStatic(Tester.class);
// Stub return value for static method call
when(Tester.sendFaqRequest(anyString(), anyString())).thenAnswer(new FirstResponseWithText());
// Call method which calls our static method 3x
OtherClass.methodThatCallsTesterStaticMethod("", "", "", false, "");
// Verify that Tester.sendFaqRequest was called 3x
verifyStatic(Tester.class, times(3));
Tester.sendFaqRequest(anyString(), anyString());
}
}
So if this does not work for you and your Maven or Gradle dependencies are also okay, the difference is maybe in your FirstResponseWithText class. Maybe you want to show it so we can all see what kind of magic you do in there. As you can see from my sample code, I had to make several educated guesses because you only share a little snippet of test code and not MCVE like you should. This way I can only speculate and actually I do not like to because it might be a waste of time for both you and myself.

How to use assertTrue?

I have:
package com.darlik.test;
import org.junit.Assert;
public class Test {
public static void main(String[] args) {
assertTrue(1, 2);
}
}
package with org.junit is set and working but in line with assertTrue i have error:
The method assertTrue(int, int) is undefined for the type Test
Why? I use Eclipse.
assertTrue is based on a single boolean condition. For example
assertTrue(1 == 2);
You need to import the statement statically to use
import static org.junit.Assert.assertTrue;
Typically, however assertEquals is used when comparing 2 parameters, e.g.
public class MyTest {
#Test
public void testAssert() throws Exception {
assertEquals(1, 2);
}
}
You have to specify the class that defines that method:
Assert.assertTrue(condition);
Furthermore you're calling the method with 2 parameters which makes no sense. assertTrue expects a single boolean expression.
Although you can also do this by using a static import:
import static org.junit.Assert.*;
which will allow you to call it as assertTrue(condition); instead.
From the doc : assertTrue(boolean) or assertTrue(String, boolean) if you want to add a message.
AssertTrue assert that a condition is true, you still have to code such condition for it to be evaluated at runtime.
Better try assertThat with matchers. Check this blog about it https://objectpartners.com/2013/09/18/the-benefits-of-using-assertthat-over-other-assert-methods-in-unit-tests/
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
....
#Test
public void testNum() {
assertThat(repo.getNum(), is(equalTo(111)));
}
Delete the module-info.java file if there is any in the project. It's not necessary and is only used if you're using Java's built-in module system.

Java : The import collides with another import statement

I have imported an Existing Java Application into my Workspace .
I see that , a class with same name is present in different packages with in the Application.
For example a class named "Status.java" is present with in
com.tata.model.common.Status;
com.bayer.frontlayer.dao.Status;
When I tried to use both of them within a class, for example as shown below
import com.tata.model.common.Status;
import com.bayer.frontlayer.dao.Status;
public class Adapter
{
}
It started giving an error in Eclipse stating
The import com.bayer.frontlayer.dao.Status collides with another import statement
Is there anyway to solve this without changing the name of the classes??
Thank you.
You can use them explicitly without importing them, so the included package name differentiates between the two:
//No imports required!
public class Adapter
{
private com.tata.model.common.Status x;
private com.bayer.frontlayer.dao.Status y;
}
You can import just one of the classes and use the fully qualified name for the other one.
e.g.
import com.tata.model.common.Status;
//import com.bayer.frontlayer.dao.Status;
class SomeClass{
void someMethod(){
new Status(); // com.tata.model.common.Status
new com.bayer.frontlayer.dao.Status(); //com.bayer.frontlayer.dao.Status
}
}
Though I think it would be less confusing in your case if you just used the fully-qualified names for both classes.
Directly apply full Class Names wherever applicable. Eg-
public class SomeClass {
public someMethod() {
com.myapp.someotherpackage.Status = "something";
com.some.other.package.Status = "otherthing";
if(com.myapp.someotherpackage.Status == com.some.other.package.Status) {
}
....
}
}

How to mock object with constructor that takes a Class?

This is the test:
import static junit.framework.Assert.assertTrue;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.whenNew;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest( {ClassUnderTesting.class} )
public class ClassUnderTestingTest {
#Test
public void shouldInitializeMocks() throws Exception {
CollaboratorToBeMocked mockedCollaborator = mock(CollaboratorToBeMocked.class);
suppress(constructor(CollaboratorToBeMocked.class, InjectedIntoCollaborator.class));
whenNew(CollaboratorToBeMocked.class)
.withArguments(InjectedAsTypeIntoCollaborator.class)
.thenReturn(mockedCollaborator);
new ClassUnderTesting().methodUnderTesting();
assertTrue(true);
}
}
These are the classes :
public class ClassUnderTesting {
public void methodUnderTesting() {
new CollaboratorToBeMocked(InjectedAsTypeIntoCollaborator.class);
}
}
public class CollaboratorToBeMocked {
public CollaboratorToBeMocked(Class<InjectedAsTypeIntoCollaborator> clazz) {
}
public CollaboratorToBeMocked(InjectedIntoCollaborator someCollaborator) {
}
public CollaboratorToBeMocked() {
}
}
public class InjectedAsTypeIntoCollaborator {
}
public class InjectedIntoCollaborator {
}
This is the error :
org.powermock.reflect.exceptions.TooManyConstructorsFoundException: Several matching constructors found, please specify the argument parameter types so that PowerMock can determine which method you're refering to.
Matching constructors in class CollaboratorToBeMocked were:
CollaboratorToBeMocked( InjectedIntoCollaborator.class )
CollaboratorToBeMocked( java.lang.Class.class )
Here comes the question: how can I make PowerMock figure out what constructor to look for?
The problematic line is the suppress. That is where the error comes from.
Perhaps it is too late for your question. I met it today and found the solution at the following url. Basically, you need to specify your argument type like.
whenNew(MimeMessage.class).**withParameterTypes(MyParameterType.class)**.withArguments(isA(MyParameter.class)).thenReturn(mimeMessageMock);
http://groups.google.com/group/powermock/msg/347f6ef1fb34d946?pli=1
Hope it can help you. :)
I didn't know of PowerMock until you wrote your question, but did some reading and found this in their documentation. Still I am not really sure if that helps you:
If the super class have several
constructors it's possible to tell
PowerMock to only suppress a specific
one. Let's say you have a class called
ClassWithSeveralConstructors that has
one constructor that takes a String
and another constructor that takes an
int as an argument and you only want
to suppress the String constructor.
You can do this using the
suppress(constructor(ClassWithSeveralConstructors.class, String.class));
method.
found at http://code.google.com/p/powermock/wiki/SuppressUnwantedBehavior
Isn't it the thing you wanted?
EDIT: Now I see, you've already tried suppressing. But are you sure you got the suppress call right? Isn't the first argument of constructor() supposed to be the class you would like to surpress the constructor in?
If using PowerMock for EasyMock you can do PowerMock.expectNew(CollaboratorToBeMocked.class, new Class[]{InjectedIntoCollaborator.class}, ...) where the Class[] is the parameter types of the constructor you're expecting to be called. This will resolve the ambiguity between the constructors.

Categories