I use a Hystrix (v. 1.5.6) command in my tested class, and I'm trying to mock it with Mockito (v. 1.10.19).
Recently I've had to add a special behavior if the command failed because of a timeout:
try {
result = command.execute();
} catch (HystrixRuntimeException err) {
if (command.isResponseTimedOut()) {
/** do stuff **/
}
/** do stuff **/;
}
This is the code in my test class :
HttpClientCommand command = mock(HttpClientCommand.class);
when(commandFactory.get(anyString(), anyString(), anyString(), anyMapOf(String.class, String.class))).thenReturn(command);
when(command.execute()).thenThrow(hystrixRuntimeException);
when(command.isResponseTimedOut()).thenReturn(false);
My HttpClientCommand extends the HystrixCommand class. The execute method is in this class, and I have no problem stubbing it.
The HystrixCommand class then extends the AbstractCommand class, where the isResponseTimedOut method is. When I try to stub it, I get a NPE from Mockito (on the when(command.isResponseTimedOut()).thenReturn(false); line, before calling any method on my tested class).
Stack trace :
java.lang.Exception: Unexpected exception, expected<my.custom.exception> but was<java.lang.NullPointerException>
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.NullPointerException
at com.netflix.hystrix.AbstractCommand.isResponseTimedOut(AbstractCommand.java:1809)
at com.netflix.hystrix.HystrixCommand.isResponseTimedOut(HystrixCommand.java:46)
at com.myClassTest.testGetLocation_shouldThrowCustomException_whenRequestException(myClassTest.java:300)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:19)
... 22 more
How can I stub this method?
OK the issue is due to a bug with CGLIB, mockito 1.x uses CGLIB. When the method to mock is declared in a non public parent, then CGLIB doesn't intercept the method, hence it executes the real code. The issue is still available on our old issue tracker : issue 212
Two options :
Write a public overload in HttpHystrixCommand that will invoke the super method, but since the abstract command have a lot of methods to handle failure, this is probalby not an option that will scale very well.
Use mockito 2. We have worked with the developer of ByteBuddy – Rafel Winterhalter – to replace CGLIB. ByteBuddy does not have the same shortcomings of CGLIB which was almost abandonned for years. Current version is 2.2.29 and at the time of this anwer regular updates are released.
Related
I have a JUnit test where I have 5 mocks and one of mocked classes is final, I enabled mock-maker-inline to overcome that problem and now test passes but at the end of test execution I also get NotAMockException at:
org.mockito.exceptions.misusing.NotAMockException: Argument passed to Mockito.mockingDetails() should be a mock, but is an instance of class ...Locals!
at org.mockito.internal.runners.DefaultInternalRunner$1$2.testFinished(DefaultInternalRunner.java:63)
at org.junit.runner.notification.SynchronizedRunListener.testFinished(SynchronizedRunListener.java:56)
at org.junit.runner.notification.RunNotifier$7.notifyListener(RunNotifier.java:190)
at org.junit.runner.notification.RunNotifier$SafeNotifier.run(RunNotifier.java:72)
at org.junit.runner.notification.RunNotifier.fireTestFinished(RunNotifier.java:187)
at org.junit.internal.runners.model.EachTestNotifier.fireTestFinished(EachTestNotifier.java:38)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:331)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:74)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:80)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
...
The mocking is very simple:
#Mock
private Locals locals; //class
#Mock
private Globals globals; // class
#Mock
private Cache cache; // interface
#Mock
private Reminds reminds; // final class
#Mock
private Employeereminds employeereminds; // class
... followed by couple of when().thenReturn() setups to make it work together
During the test mocks looks like this:
locals = {Locals#3233}
globals = {Globals#3234}
cache = {Cache$MockitoMock$665734991#3237} "cache"
reminds = {Reminds#3235}
employeereminds = {Employeereminds#3236}
I am using Mockito 2.25.0 also tried 2.28.2 but no difference.
I can refactor my test to also test the content of final class but I prefer my test isolated. I could also use powermock but have seen similar problems reported with powermock.
Did anybody stumble upon such issue and found a decent workaround?
EDIT: I did some more investigation, I removed Locals Mock and got same error on Globals mock. Then I removed Globals mock and got (!?) following exception (# v2.28.2):
org.mockito.exceptions.misusing.NotAMockException: Argument passed to Mockito.mockingDetails() should be a mock, but is an instance of class Cache$MockitoMock$149288076!
at org.mockito.internal.runners.DefaultInternalRunner$1$2.testFinished(DefaultInternalRunner.java:63)
at org.junit.runner.notification.SynchronizedRunListener.testFinished(SynchronizedRunListener.java:56)
at org.junit.runner.notification.RunNotifier$7.notifyListener(RunNotifier.java:190)
at org.junit.runner.notification.RunNotifier$SafeNotifier.run(RunNotifier.java:72)
at org.junit.runner.notification.RunNotifier.fireTestFinished(RunNotifier.java:187)
at org.junit.internal.runners.model.EachTestNotifier.fireTestFinished(EachTestNotifier.java:38)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:331)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:74)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:80)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
...
Ok, I've found the issue:
I was invoking
Mockito.framework().clearInlineMocks();
in a code invoked by #After annotation, but the correct way is to do it in code invoked by #AfterClass annotation, otherwise Mockito own verification is run after you cleared the mocks.
I'm using Room on Android. So I've got my data model class with the proper Room annotations and a single public constructor. It uses a builder pattern and tries to be immutable. It's here.
Then I've got my #Dao-annotated interface with #Query, #Update, and #Insert annotations next to all the method declarations as it should be. Right over here.
Finally, I've got my Dao test class, which uses Room.inMemoryDatabaseBuilder. It is here.
So when I run the tests in GoalsDaoTest, they all pass except for two: One that uses the Dao method annotated #Update, and another whose Dao method uses an SQL UPDATE command inside its #Query.
Here's my test set-up and tear-down, using Room.inMemoryDatabaseBuilder:
#Before
public void initDb() {
mDatabase = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext(),
SelfCareDatabase.class).build();
}
#After
public void closeDb() {
mDatabase.close();
}
Here's the first failing test:
#Test
public void updateArchivedAndGetById() {
// When inserting a goal
mDatabase.goalDao().insertGoal(GOAL);
// When the goal is updated
mDatabase.goalDao().updateArchived(GOAL.getId(), true);
// When getting the goal by id from the database
Goal loaded = mDatabase.goalDao().getGoalById(ID);
// The loaded data contains the expected values
assertGoal(loaded, GOAL.getId(), GOAL.getTitle(), GOAL.getInterval(), GOAL.getPolarity(), true, GOAL.getTouched());
}
Here's the error it produces when I run it:
java.lang.NoSuchMethodError: No interface method updateArchived(Ljava/lang/String;Z)V in class Lcom/beatboxchad/android/selfcaredashboard/data/source/local/GoalsDao; or its super classes (declaration of 'com.beatboxchad.android.selfcaredashboard.data.source.local.GoalsDao' appears in /data/app/com.beatboxchad.android.selfcaredashboard-1/base.apk)
at com.beatboxchad.android.selfcaredashboard.data.source.local.GoalsDaoTest.updateArchivedAndGetById(GoalsDaoTest.java:155)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at android.support.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
at android.support.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:58)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:375)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1939)
And yet, that method is properly declared and annotated in the GoalsDao class:
/**
* Update the Archived status of a goal
*
* #param goalId id of the goal
* #param archived status to be updated
*/
#Query("UPDATE goals SET archived = :archived WHERE entryid = :goalId")
void updateArchived(String goalId, boolean archived);
Here's the other test:
#Test
public void updateGoalAndGetById() {
// When inserting a goal
mDatabase.goalDao().insertGoal(GOAL);
// When the goal is updated
Goal updatedGoal = new Goal.Builder(ID)
.setTitle(TITLE2)
.setPolarity(POLARITY2)
.setInterval(INTERVAL2)
.setArchived(ARCHIVED2)
.setTouched(TOUCHED2)
.build();
mDatabase.goalDao().updateGoal(updatedGoal);
// When getting the goal by id from the database
Goal loaded = mDatabase.goalDao().getGoalById(ID);
// The loaded data contains the expected values
assertGoal(loaded, ID, TITLE2, INTERVAL2, POLARITY2, ARCHIVED2, TOUCHED2);
}
Here's its error:
java.lang.NoSuchMethodError: No interface method updateGoal(Lcom/beatboxchad/android/selfcaredashboard/data/Goal;)I in class Lcom/beatboxchad/android/selfcaredashboard/data/source/local/GoalsDao; or its super classes (declaration of 'com.beatboxchad.android.selfcaredashboard.data.source.local.GoalsDao' appears in /data/app/com.beatboxchad.android.selfcaredashboard-1/base.apk)
at com.beatboxchad.android.selfcaredashboard.data.source.local.GoalsDaoTest.updateGoalAndGetById(GoalsDaoTest.java:140)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at android.support.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
at android.support.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:58)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:375)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1939)
And yet! Confound me! What madness causes the computer to lie? GoalsDao.java excerpt:
/**
* Update a goal.
*
* #param goal goal to be updated
* #return the number of goals updated. This should always be 1.
*/
#Update
int updateGoal(Goal goal);
I've exhausted all the low-hanging fruit on this one. Everything appears to conform to the docs (though I'm suspicious of my immutable builder'd Goal class), and I've attempted to follow advice given in the following places:
Why Room entities don't work with immutable properties in Android
Espresso Test Failing: No interface method trackUsage() in UsageTracker.java
Room Persistence Library run time exception when calling Rooms inMemoryBuilder method
But I'm not using Kotlin nor the #Relation annotation, and even when I played with all kinds of different versions in my build.gradle files, it stayed broken. The bright side is, I've learned a lot about that boring part. tl;dr I'm stumped.
Just in case it's helpful context, my app is strongly based on the todo‑mvvm‑databinding example from https://github.com/googlesamples/android-architecture. I mention this because everything works in the sample, but I've added some complexity and perhaps made a mistake along the way that somebody more experienced will recognize. Particularly, I've mangled that #Entity Goal class (Task in the example app), trying to keep it immutable and adding the builder pattern and several attributes. I'm not done mangling it either -- touched is about to be its own table.
I'm also unskilled in troubleshooting whatever turns an interface and a bunch of annotations into code. Any advice about where to look in resolving this is as useful as the answer it'll lead to. I'm new to Android Studio, Java, and the whole build process.
Thank you!
Invalidate caches and restart in android studio helped
I was adding suspend to some functions in the DAO and ran into this. A simple Build\Clean fixed it
This question already has answers here:
How to mock a final class with mockito
(28 answers)
Closed 5 years ago.
I have one class which is final, which has one method on which I want to perform certain action. Because of this I want to create object of final class. But I am unable to create it, following is my class.
public final class A {
private String name;
A(String name){
this.name = name;
}
public String getName(){
return name;
}
}
In my junit test case I want to create object of that class, like below
Class TestA{
#Test
public void testA(){
A a = mock(A.class);
when(a.getName()).then("ABC"); //on this line i am getting exception
}
}
I have tried it by using new keyword also, but not working. So is there anyway to create a mock object of final class?
Following exception I facing,
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class A
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types
at com.rocket.map.resources.TestA.testA(TestA.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
try using this.
Use the #RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
Use the #PrepareForTest(ClassWithFinal.class) annotation at the class-level of the test case.
Use PowerMock.createMock(ClassWithFinal.class) to create a mock object for all methods of this class (let's call it mockObject).
Use PowerMock.replay(mockObject) to change the mock object to replay mode.
Use PowerMock.verify(mockObject) to change the mock object to verify mode.
Also refer this answer - link
And Tutorial.
Both look easy to implement.
This is not possible with Mockito v1
Please look into this link. I think in advance version or powermockito you can do this.Powermockito example
This question already has answers here:
Android Studio 3.0 Canary 1: Kotlin tests or Java tests referring to Kotlin classes fail
(4 answers)
Closed 5 years ago.
This is the class that I'm trying to call from my unit test
package bj.discogsbrowser.artistreleases
class ArtistResultFactory {
companion object {
#JvmStatic fun buildArtistResult(members: Int): ArtistResult {
val artistResult = ArtistResult()
artistResult.nameVariations = listOf("ye")
artistResult.dataQuality = "really good quality, we have the best qualities"
return artistResult
}
}
}
This is what the test looks like:
#Test
fun setArtistNoMembers_displaysNoMembers() {
controller.setArtist(ArtistResultFactory.buildArtistResult(0))
...
assertEquals(copyOfModels.size, 8)
}
Same test in Java (which also fails):
#Test
public void setArtistNoMembers_displaysNoMembers()
{
controller.setArtist(ArtistResultFactory.buildArtistResult(0));
...
assertEquals(copyOfModels.size(), 8);
}
In both Kotlin and Java I get the stack trace:
java.lang.NoClassDefFoundError: bj/discogsbrowser/artistreleases/ArtistResultFactory
at bj.discogsbrowser.artist.ArtistControllerTest.setArtistNoMembers_displaysNoMembers(ArtistControllerTest.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:488)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:209)
at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:109)
at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:36)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:63)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Caused by: java.lang.ClassNotFoundException: bj.discogsbrowser.artistreleases.ArtistResultFactory
at org.robolectric.internal.bytecode.SandboxClassLoader.getByteCode(SandboxClassLoader.java:161)
at org.robolectric.internal.bytecode.SandboxClassLoader.maybeInstrumentClass(SandboxClassLoader.java:108)
at org.robolectric.internal.bytecode.SandboxClassLoader.findClass(SandboxClassLoader.java:101)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 32 more
I feel it may have something to do with my sourceSets as when I remove those lines then the code won't compile.
sourceSets {
test {
java.srcDirs += "$projectDir/src/testShared"
}
androidTest {
java.srcDirs += "$projectDir/src/testShared"
}
}
ArtistResultFactory is located in /src/testShared/. When it was a Java class, the tests ran fine.
My app build.gradle includes
apply plugin: "kotlin-android"
apply plugin: 'kotlin-android-extensions'
at the top.
You need to make it an "object" instead of "class" in order to access it singleton style in Kotlin.
If you do make it an object (which is the right thing to do with things like a Factory which are typically singletons), then in Java you will I believe have to do a .getINSTANCE() before you can access the method (not sure if you can make it static or not) as I don't believe companion objects are allowed on objects in Kotlin (I might be mistaken on that though).
I might be on the wrong track here so please correct me if so.
I have a data model with a member called action which is an enum. So looks like this:
Contract class:
public class Contract {
public Action action;
public Action getAction() {
return action;
}
public void setAction(Action action) {
this.action = action;
}
}
Action class:
public enum Action {
CREATE, AMEND, RENEWAL
}
Now, the problem is that I can not replicate this data model in Kie Workbench as it seems not to support enums? Or maybe I do not know how to implement them?
Which in turn means that when I fetch the rules via the Kie Execution Server, because I can not have an action member of type Action (which is an enum) the following rule will never get fired:
rule "Contract rule"
when
$c : Contract ( action.equals("CREATE") )
then
System.out.println("This order action is: " + $c.getAction());
end
Is there a workaround here? Am I missing something?
If you wanna see the error that I get when I implement the following code, here it is:
java.lang.NoSuchMethodError: com.heg.projectdelta.contractcreator.model.Contract.getAction()Lcom/heg/projectdelta/contractcreator/model/Action;
at com.heg.projectdelta.contractcreator.model.Rule_Contract_rule116883127.defaultConsequence(Rule_Contract_rule116883127.java:7)
at com.heg.projectdelta.contractcreator.model.Rule_Contract_rule116883127DefaultConsequenceInvokerGenerated.evaluate(Unknown Source)
at com.heg.projectdelta.contractcreator.model.Rule_Contract_rule116883127DefaultConsequenceInvoker.evaluate(Unknown Source)
at org.drools.core.common.DefaultAgenda.fireActivation(DefaultAgenda.java:1114)
at org.drools.core.phreak.RuleExecutor.fire(RuleExecutor.java:160)
at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:108)
at org.drools.core.common.DefaultAgenda.fireNextItem(DefaultAgenda.java:1016)
at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1302)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1289)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1262)
at com.heg.projectdelta.cedroolscore.service.DroolsService.fireAllRules(DroolsService.java:115)
at com.heg.projectdelta.contractcreator.service.impl.DroolsWebServiceImpl.fireRules(DroolsWebServiceImpl.java:66)
at com.heg.projectdelta.contractcreator.integration.DroolsWebServiceTest.testFireRules(DroolsWebServiceTest.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Ta
I don't know how the workbench would permit or refute the use of enum classes, but if you were to write the rule in plain DRL, it would have to be
rule "Contract rule"
when
$c : Contract ( action == Action.CREATE )
then
System.out.println("This order action is: " + $c.getAction());
end