ConstraintCollectors not recognized in Spring Boot (STS) - java

I'm trying to make use of the Optaplanner constraintprovider, which works fine until I want to use the count() ConstraintCollector.
I try to use it in a groupBy-clause, but I get the error: The method count() is undefined for the type hamxConstraintProvider
I was under the assumption this should "just work"? Or should I write my own method for count? I couldn't find that happening in the examples, but seem unable to fix it either. Am I overlooking an import?
import org.optaplanner.core.api.score.stream.Constraint;
import org.optaplanner.core.api.score.stream.ConstraintFactory;
import org.optaplanner.core.api.score.stream.ConstraintProvider;
import org.optaplanner.core.api.score.stream.uni.UniConstraintCollector;
import org.optaplanner.core.api.score.stream.bi.BiConstraintCollector;
import org.optaplanner.core.api.score.stream.ConstraintCollectors.*;
import org.optaplanner.core.api.score.stream.Joiners.*;
...
public class hamxConstraintProvider implements ConstraintProvider{
#Override
public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
return new Constraint[] {
skillUnavailable(constraintFactory),
balancedJobs(constraintFactory)
};
}
...
private Constraint balancedJobs(ConstraintFactory factory) {
return factory.from(Job.class)
.groupBy(Job::getEmployee,count())
.penalize("unbalancedEmployeeUsage", HardSoftScore.ONE_SOFT,count);
}

Instead of
import org.optaplanner.core.api.score.stream.ConstraintCollectors.*;
import org.optaplanner.core.api.score.stream.Joiners.*;
use static imports:
import static org.optaplanner.core.api.score.stream.ConstraintCollectors.*;
import static org.optaplanner.core.api.score.stream.Joiners.*;
The former imports classes, the latter imports static methods.

count() and countLong() are methods of ConstraintCollectors. If it compiles but doesn't run, you're likely not providing Spring's ClassLoader to the SolverConfig.
In the next release, 7.32, we're releasing optaplanner-spring-boot-starter, which will make Spring Boot integration a lot easier (it just auto injects a SolverManager (or SolverFactory, but the former is the latter on steriods)

Related

Spring Boot Integration Test with awaitility and #SpyBean not working, because #SpyBean is always null

I want to test my scheduled task, so I followed this tutorial
#SpringJUnitConfig(SchedulerConfig.class)
public class MailJobFinderTaskIT {
#SpyBean
private MailJobFinderTask mailJobFinderTask;
#Test
public void whenWaitThreeSecond_ThenTaskCalledThreeTimes(){
await()
.atMost(Duration.ofSeconds(3))
.untilAsserted(() -> verify(mailJobFinderTask, atLeast(3)).findEmailJobs());
}
}
But actually it does not work, because the the following error
org.mockito.exceptions.misusing.NullInsteadOfMockException:
Argument passed to verify() should be a mock but is null!
Examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
not: verify(mock.someMethod());
Also, if you use #Mock annotation don't miss initMocks()
here is the signature of my Task-Class
#Component
public class MailJobFinderTask extends SuppressedLogPoller {
....
}
#Scheduled(fixedRate = 1000)
public void findEmailJobs() {
.
.
}
I tried already to change the Annotation to #SpringBootTest and also tried to used #MockBean instead of #SpyBean but without any success. Actually I do not understand why my bean mailJobFinderTask is not created
Your code seems to work fine on my system, but I had to do a few changes.
I would recommend these as starting points to your troubleshooting. Also, you haven't mentioned if you can successfully replicate the linked tutorial, which also runs fine on my system. If you haven't, I would recommend trying the tutorial first, confirming it works, and then adding your own code.
If the below does not help you, then it could be that the issue is not in the part of the code you posted. In that case, sharing the full code would help us better troubleshoot the problem. But for now, maybe pay particular attention to the import statements and the main changes listed below.
Changes from your code
I changed the Duration.ofSeconds(3) method to Duration.FIVE_SECONDS. The reason for this is that the former is from java.time package, while await() expects a Duration class from the awaitility package. I just used FIVE_SECONDS for compatibility purposes.
I had to remove the "extends SuppressedLogPoller" part, as I did not have access to this class. I would also recommend removing it and adding this back again to see if it is causing the issue.
Test class code
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.awaitility.Duration;
import static org.awaitility.Awaitility.await;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.verify;
#SpringJUnitConfig(ScheduledConfig.class)
public class MailJobFinderTaskIT {
#SpyBean
private MailJobFinderTask mailJobFinderTask;
#Test
public void whenWaitThreeSecond_ThenTaskCalledThreeTimes(){
await()
.atMost(Duration.FIVE_SECONDS)
.untilAsserted(() -> verify(mailJobFinderTask, atLeast(7)).findEmailJobs());
}
}
Domain class
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
#Component
public class MailJobFinderTask {
#Scheduled(fixedRate = 1200)
public void findEmailJobs() {
}
}
As mentioned in the error message:
Examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
not: verify(mock.someMethod());
You should update the following line:
.untilAsserted(() -> verify(mailJobFinderTask, atLeast(3)).findEmailJobs());
as shown below:
.untilAsserted(() -> verify(mailJobFinderTask, atLeast(3)).findEmailJobs();

In java, why can I only import abstract classes?

In my Java I have a class import:
import cc.hyperium.mods.HyperiumModIntegration;
however, it fails to import with error Cannot resolve symbol 'HyperiumModIntegration'.
The class I'm importing looks like this:
package cc.hyperium.mods;
public class HyperiumModIntegration {
public HyperiumModIntegration() {
}
}
Weirdly, if I make the class abstract, it imports just fine.
IntelliJ will show the class in code completion, however.
Invalidating caches and restarting in IntelliJ fixed it.
(Note to self: stop using EAP.)

Import for mockito

I am trying to put statement like
when(myDao.fetchTree(anyLong())).thenReturn(myTreeList);
and I have import
import static org.mockito.Mockito.when;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.thenReturn; //not importing
import for thenReturn is not mapping. Is this a version issue? I am using Mockito 1.8.4.
Mockito's when returns an object of class OngoingStubbing. This class has a method thenReturn(), and that's what gets called in your example code. No additional import is needed.
when(myDao.fetchTree(anyLong())).thenReturn(myTreeList);
could be broken up as
OngoingStubbing thing = when(myDao.fetchTree(anyLong()));
thing.thenReturn(myTreeList);
You are just calling the thenReturn method of OngoingStubbing.
It should be enough if you use:
import static org.mockito.Mockito.*;
And remove the rest.
Your question: Is this a version issue?
I'd say NO, that is not a version issue.
As suggested previously, you should
create minimal test with this code in test
when(myDao.fetchTree(anyLong())).thenReturn(myTreeList);
run this code from command-line (not inside in STS or any IDE or something a like)
Q: Why run it from command-line and avoid using IDE-s etc?
A: Because sometimes code parsers and checkers and validators of your favorited IDE reports false positives about some corner-cases in code.

PowerMock not stubbing static method properly?

I'm trying to write a VERY simple test, using powermock and Robolectric. Here's my code:
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.robolectric.RobolectricTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
#RunWith(RobolectricTestRunner.class)
#PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
#PrepareForTest(BadStaticClass.class)
public class SomeActivityTest {
#Test
public void testSomething() {
PowerMockito.mockStatic(BadStaticClass.class);
Mockito.when(BadStaticClass.dontWantThisMethod()).thenReturn(false);
new SomeActivity().usesStatic();
}
}
Basically, i have a class, "SomeActivity", and it has a method that makes a call to BadStaticClass.dontWantThisMethod(). i want that static method to be stubbed out.
why is my code not working?
i kept getting errors like:
you are trying to stub a final method, you naughty developer!
which, i thought the whole point of PowerMock was to not see that.
According to the PowerMock API you have to include #RunWith(PowerMockRunner.class) for certain versions of JUnit, etc. However you also need to be using #RunWith(RobolectricTestRunner.class) and cannot specify more than one #RunWith on a Class.
So what to do?
I suspect you can keep your code above and introduce a JUnit #Rule (see: PowerMockRule docs) and also described in this similar post. Just be sure you check the versions of the Jars you are using so that they match those described in that other SO post. All too often things just won't work unless you get compatible versions, and it's not always obvious what versions are compatible.

Why is my import of the containsString method not working?

I've written the simple Java script below in order to learn more about TDD, IntelliJ and Java itself.
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.both;
public class JUnit_Dummy {
private StringJoiner joiner;
private List<String> strings;
#Before
public void setUp() throws Exception {
strings = new ArrayList<String>();
joiner = new StringJoiner();
}
....
#Test
public void shouldContainBothStringsWhenListIsTwoStrings() {
strings.add("one");
strings.add("two");
assertThat(joiner.join(strings),
both(containsString("A")).
and(containsString("B")));
}
}
_____________
import java.util.List;
public class StringJoiner {
public String join(List<String> strings) {
if(strings.size() > 0) {
return (strings.get(0);
}
return "";
}
}
I'm trying to use the "containsString" method inside an assertion, but IntelliJ keeps telling me that it "cannot resolve method 'containsString(java.lang.String)". This despite the fact that the jUnit docs (http://junit.sourceforge.net/javadoc/org/junit/matchers/JUnitMatchers.html#containsString(java.lang.String)) tell me that this method does accept a String parameter.
I've tried swapping out various import statements, including the following:
import static org.hamcrest.Matcher.containsString;
import static org.hamcrest.Matcher.*;
import static org.hamcrest.CoreMatchers.*;
The best that I get is a greyed-out import statement telling me that the import statement is unused. Not sure what the problem is, any help would be appreciated.
UPDATE:
Here is the exact compiler error:
java: cannot find symbol
symbol: method containsString(java.lang.String)
location: class JUnit_Dummy
I thought I had tried every worthwhile import statement already, but this one did the trick:
import static org.junit.matchers.JUnitMatchers.*;
I faced the same issue with a Spring Boot app.
Seems like this is a dependency ordering issue.. one of the dependencies mentioned in pom.xml before the "spring-boot-starter-test" artifact was overriding the hamcrest version.
So all I did was change the order (moved this dependency up):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
I'm using Spring Boot 1.5.7.RELEASE.
We are supposed to use containsString method of hamcrest library.
My suggestion would be to stick to Junit 4 and import hamcrest library 1.3 in your build path. This would do the trick.
This will allow you to access other features of hamcrest library as well.
The solution can also be found by adding the required static imports manually. Or you can configure the required static imports in favorites tab of eclipse.
try this instead
import static org.hamcrest.CoreMatchers.*;
I'm working with MAVEN - doing a tutorial and I ran into this same issue.
I used the "import static org.hamcrest.CoreMatchers.*;" solution and that failed.
So I then moved JUNIT to be first on the list in the POM file - and that solved it.

Categories