My android app is crashing at activity launch from the main activity, but only when I initialize a SharedPreferences object.
In Main Activity:
package my.investing.investingtestapp
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnPlay.setOnClickListener {
// Handler code here.
val I = Intent(this, PlayActivity::class.java)
startActivity(I);
}
}
}
In Play Activity:
package my.company.example
import android.content.Context
import android.content.SharedPreferences
import android.content.SharedPreferences.Editor
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class PlayActivity : AppCompatActivity() {
val prefs: SharedPreferences? by lazy { this.getPreferences(Context.MODE_PRIVATE) }
val editor: Editor = prefs!!.edit()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_play2)
}
}
This is true also for:
val prefs = this.getPreferences(Context.MODE_PRIVATE)
error:
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{my.company.example/my.company.example.PlayActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3365)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.content.ContextWrapper.getPackageName(ContextWrapper.java:149)
at android.app.Activity.getLocalClassName(Activity.java:6738)
at android.app.Activity.getPreferences(Activity.java:6782)
at my.company.example.PlayActivity$prefs$2.invoke(PlayActivity.kt:39)
at my.company.example.PlayActivity$prefs$2.invoke(PlayActivity.kt:37)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at my.company.example.PlayActivity.getPrefs(Unknown Source:2)
at my.company.example.PlayActivity.(PlayActivity.kt:40)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
at android.app.Instrumentation.newActivity(Instrumentation.java:1253)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3353)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Specifically, it's this:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method
'java.lang.String android.content.Context.getPackageName()' on a null object
reference at
android.content.ContextWrapper.getPackageName(ContextWrapper.java:149) at
android.app.Activity.getLocalClassName(Activity.java:6738) at
android.app.Activity.getPreferences(Activity.java:6782) at
my.company.example.PlayActivity$prefs$2.invoke(PlayActivity.kt:39) at
It's crashing because you're trying to call getPackageName() on a null Context, which is happening through a getPreferences() call caused by your prefs object at line 39 of PlayActivity.kt.
Those member functions are initialised when your Activity is constructed, but at that point the Activity doesn't have a Context yet - that happens later in the lifecycle, and it's ready by the time onCreate is called. So some things have to be initialised later (lateinit is useful for things like this)
Your lazy delegate would work normally - by the time it's accessed by something, the Activity would have its Context. But you're accessing it in the next line when you initialise editor, so it's always running at construction anyway and there's no point making it lazy.
You probably shouldn't hold an editor reference like that anyway, especially with things like KTX Core that let you edit, set and commit all in one shot:
sharedPreferences.edit { putBoolean("key", value)
Definitely don't use !! on a thing that definitely can be null sometimes, you'll only end up regretting it
You cannot call methods that you inherit from Activity until inside of the onCreate() method. Until then, things are not set up yet.
So intialize your objects in onCreate() method.
Try to editor = prefs?.edit() into oncreate after setcontentview.
Btw operator !! Is not safety, because it could throw KotlinNullPointerException
Related
i am writing unit test for some usecase, but i found that after i add withContext(IO) in my repository and than i run my unit test again, everything works fine except the test that expect to be fail and return exception, I've read several sites about testing coroutines but I found nothing to solve it, maybe I missed something? this is my repository
class HaditsRepository #Inject constructor(
private val remote: IRemoteHaditsDatasource,
#IoDispatcher private val dispatcher: CoroutineDispatcher
): IHaditsRepository {
override fun getCategories(): Flow<ResultOf<GetCategoriesResponse>> {
return flow {
emit(ResultOf.Loading())
val result = withContext(dispatcher){ remote.getCategories() }
emit(ResultOf.Success(result))
}.catch { e->
emit(ResultOf.Failure(e))
}
}
}
this is my usecase
class GetCategoriesUsecase #Inject constructor(
private val repository: IHaditsRepository
) {
operator fun invoke() = repository.getCategories()
}
and this is my unit test
#OptIn(ExperimentalCoroutinesApi::class)
class GetCategoriesUsecaseTest {
// Mock Initialize
private lateinit var openMock: AutoCloseable
// Coroutines
private val testDispatcher = StandardTestDispatcher()
// System Under Test
private lateinit var sut: GetCategoriesUsecase
// Given Conditions
private suspend fun givenFailure(){
whenever(mockDSR.getCategories()).thenThrow(dummyException)
}
// Setup
#Before
fun setup(){
openMock = MockitoAnnotations.openMocks(this)
Dispatchers.setMain(testDispatcher)
val repository = HaditsRepository(mockDSR, testDispatcher)
sut = GetCategoriesUsecase(repository)
}
#After
fun close(){
openMock.close()
Dispatchers.resetMain()
}
....
// FAIL HEREEEEE
#Test
fun `(-) Given failure - When SUT is called - Then assert result has correct Response`(){
runTest {
// Given
givenFailure()
// When
val result = sut().last() as ResultOf.Failure
// Then
Assert.assertEquals(dummyException, result.exception)
}
}
}
and this is what I got after I ran the test
expected: java.lang.RuntimeException<java.lang.RuntimeException> but was: java.lang.RuntimeException<java.lang.RuntimeException>
java.lang.AssertionError: expected: java.lang.RuntimeException<java.lang.RuntimeException> but was: java.lang.RuntimeException<java.lang.RuntimeException>
at org.junit.Assert.fail(Assert.java:89)
at org.junit.Assert.failNotEquals(Assert.java:835)
at org.junit.Assert.assertEquals(Assert.java:120)
at org.junit.Assert.assertEquals(Assert.java:146)
at id.co.haditsku.usecase.GetCategoriesUsecaseTest$(-) Given failure - When SUT is called - Then assert result has correct Response$1.invokeSuspend(GetCategoriesUsecaseTest.kt:130)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at kotlinx.coroutines.test.TestDispatcher.processEvent$kotlinx_coroutines_test(TestDispatcher.kt:28)
at kotlinx.coroutines.test.TestCoroutineScheduler.tryRunNextTaskUnless$kotlinx_coroutines_test(TestCoroutineScheduler.kt:100)
at kotlinx.coroutines.test.TestCoroutineScheduler.advanceUntilIdleOr$kotlinx_coroutines_test(TestCoroutineScheduler.kt:120)
at kotlinx.coroutines.test.TestCoroutineScheduler.advanceUntilIdle(TestCoroutineScheduler.kt:113)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTestCoroutine(TestBuilders.kt:237)
at kotlinx.coroutines.test.TestBuildersKt.runTestCoroutine(Unknown Source)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$1$1.invokeSuspend(TestBuilders.kt:167)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$1$1.invoke(TestBuilders.kt)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$1$1.invoke(TestBuilders.kt)
at kotlinx.coroutines.test.TestBuildersJvmKt$createTestResult$1.invokeSuspend(TestBuildersJvm.kt:13)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at kotlinx.coroutines.test.TestBuildersJvmKt.createTestResult(TestBuildersJvm.kt:12)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest(TestBuilders.kt:166)
at kotlinx.coroutines.test.TestBuildersKt.runTest(Unknown Source)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest(TestBuilders.kt:154)
at kotlinx.coroutines.test.TestBuildersKt.runTest(Unknown Source)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest$default(TestBuilders.kt:147)
at kotlinx.coroutines.test.TestBuildersKt.runTest$default(Unknown Source)
at id.co.haditsku.usecase.GetCategoriesUsecaseTest.(-) Given failure - When SUT is called - Then assert result has correct Response(GetCategoriesUsecaseTest.kt:124)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
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.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
pleaseee hellppp
There is a strange issue where equality checks of Exceptions fail across coroutine boundaries even though they should be the same. It seems to be related to Exceptions being recreated using reflection and is discussed in detail here. It is something that has been dealt with in the tests of libraries like Turbine. There they use a custom exception that avoids this problem like the following:
/**
* This type prevents coroutines from breaking referential equality by
* reflectively creating new instances.
*/
internal class CustomRuntimeException(
message: String?,
override val cause: Throwable? = null,
) : RuntimeException(message)
I've successfully used a similar approach. So this is what you'll want to use for your dummyException.
I found the following statement in the book Groovy In Action, 2nd Edition:
Category use is confined to the current thread
What does this statement actually mean ?
It means you are able to call methods added via category class in the same thread only. Consider following example:
class StringUtils {
static String transform(String source) {
return source.toUpperCase().reverse().substring(0, source.length() / 2 as int)
}
}
use (StringUtils) {
println "Lorem ipsum".transform()
}
In this example we are adding String.transform() method via category. Running this example produces following output:
MUSPI
In this example we have used category class in the main thread and we have called String.transform() method in the main thread as well.
Now let's change this example a little bit and let's call String.transform() method outside main thread by calling it in the newly started thread:
class StringUtils {
static String transform(String source) {
return source.toUpperCase().reverse().substring(0, source.length() / 2 as int)
}
}
use (StringUtils) {
Thread.start {
println "Lorem ipsum".transform()
}
}
We have used StringUtil category class in the main thread and we call this method from Thread-1 thread. Let's see what happens when we run it:
Exception in thread "Thread-1" groovy.lang.MissingMethodException: No signature of method: java.lang.String.transform() is applicable for argument types: () values: []
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:49)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at script$_run_closure1$_closure2.doCall(script.groovy:9)
at script$_run_closure1$_closure2.doCall(script.groovy)
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.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at groovy.lang.Closure.call(Closure.java:414)
at groovy.lang.Closure.call(Closure.java:408)
at groovy.lang.Closure.run(Closure.java:495)
at java.lang.Thread.run(Thread.java:748)
An exception is thrown, because String.transform() does not exist in scope of Thread-1 thread - it exists only in main thread.
But let's assume that we have to make this method available in Thread-1 thread scope. We can make it happened by defining use(StringUtils){} inside the Thread-1 block, e.g.
class StringUtils {
static String transform(String source) {
return source.toUpperCase().reverse().substring(0, source.length() / 2 as int)
}
}
Thread.start {
use(StringUtils) {
println "Lorem ipsum".transform()
}
}
Now everything is fine - category usage block is defined inside Thread-1 and we call String.transform() method from the same thread. Running this example produces expected output to the console:
MUSPI
This is what
Category use is confined to the current thread
means in practice.
But how this method gets called?
When we call:
"Lorem ipsum".transform()
from the above example, following Groovy method handles invocation of transform() method:
groovy.lang.MetaClassImpl.invokeMethod(Class sender, Object object, String methodName, Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass)
You can find it at line 1044 (Groovy 2.4.12). transform() method does not exist in class String so Groovy has to find its implementation somewhere else. In this case the method is found in line 1055:
MetaMethod method = null;
if (CLOSURE_CALL_METHOD.equals(methodName) && object instanceof GeneratedClosure) {
method = getMethodWithCaching(sender, "doCall", arguments, isCallToSuper);
}
Most important part of this method is line 1283:
if (!isCallToSuper && GroovyCategorySupport.hasCategoryInCurrentThread()) {
return getMethodWithoutCaching(sender, methodName, MetaClassHelper.convertToTypeArray(arguments), isCallToSuper);
} else {
....
}
GroovyCategorySupport.hasCategoryInCurrentThread() checks if the category is used in the current thread (ThreadLocal is used in this case).
If you trace what happens next you will get to the MetaClassImpl line 690 where getMethods(Class sender, String name, boolean isCallToSuper) is located. In line 706 this method calls:
List used = GroovyCategorySupport.getCategoryMethods(name);
And this is the final part that actually finds the method by its name in the category class. Later it checks if the method is static and if it expects a parameter with a valid type (String in this case).
I wrote a module that defines a service:
public interface TranslationService {
// a method.
}
... a module that implements the service:
#Component(
immediate = true,
configurationPid = "my.TranslationConfiguration"
)
public class TranslationServiceImpl implements TranslationService {
log.info("Constructor " + getClass().getName()
+ " " + System.identityHashCode(this));
#Activate
#Modified
protected void activate(Map<String, Object> properties) {
log.info("Configuring " + translationService.getClass().getName()
+ " " + System.identityHashCode(this));
configuration = ConfigurableUtil.createConfigurable(
TranslationConfiguration.class, properties);
}
// an implementation of the method.
}
with its service activator:
public class ServiceActivator implements BundleActivator {
private ServiceRegistration registration;
#Override
public void start(BundleContext context) throws Exception {
registration = context.registerService(TranslationService.class.getName(), new TranslationServiceImpl(), null);
}
[...]
}
... and a module that uses the service:
#Component(
immediate = true,
configurationPid = [...]
service = Portlet.class
)
public class TranslationPortlet extends MVCPortlet {
#Reference(unbind = "-")
protected void setTranslationService(TranslationService translationService) {
log.info("Using " + translationService.getClass().getName()
+ " " + System.identityHashCode(translationService));
this.translationService = translationService;
}
private TranslationService translationService;
}
Log
Log when I start (via Gogo Shell) the API and implementation modules:
Constructor my.TranslationServiceImpl 606817095
Service registered.
STARTED my.impl_1.0.0 [538]
Constructor my.TranslationServiceImpl 362465287
Configuring my.TranslationServiceImpl 362465287
Then when I start (via Gogo Shell) the using module:
STARTED my.app_1.0.0 [558]
Using my.TranslationServiceImpl 606817095
Question
Why are two instances being used?
How to make all modules use the same instance of my service implementation?
Details
Stacktraces of the two times the implementation constructor is called:
my.TranslationServiceImpl.<init>(TranslationServiceImpl.java:56)
my.ServiceActivator.start(ServiceActivator.java:24)
org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:774)
org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1)
java.security.AccessController.doPrivileged(Native Method)
org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:767)
org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:724)
org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:951)
org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:328)
org.eclipse.osgi.container.Module.doStart(Module.java:566)
org.eclipse.osgi.container.Module.start(Module.java:434)
org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:402)
org.apache.felix.gogo.command.Basic.start(Basic.java:729)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.apache.felix.gogo.runtime.Reflective.invoke(Reflective.java:137)
Then:
my.TranslationServiceImpl.<init>(TranslationServiceImpl.java:56)
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
java.lang.reflect.Constructor.newInstance(Constructor.java:423)
java.lang.Class.newInstance(Class.java:442)
org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:236)
org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:108)
org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:906)
org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:879)
org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:748)
org.apache.felix.scr.impl.manager.AbstractComponentManager.enableInternal(AbstractComponentManager.java:674)
org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:429)
org.apache.felix.scr.impl.manager.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:657)
org.apache.felix.scr.impl.BundleComponentActivator.initialEnable(BundleComponentActivator.java:341)
org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:403)
org.apache.felix.scr.impl.Activator.access$200(Activator.java:54)
org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:278)
org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)
org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:232)
org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:482)
org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:1)
org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232)
org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:444)
org.eclipse.osgi.internal.framework.BundleContextImpl.dispatchEvent(BundleContextImpl.java:905)
org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)
org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEventPrivileged(EquinoxEventPublisher.java:165)
org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEvent(EquinoxEventPublisher.java:75)
org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEvent(EquinoxEventPublisher.java:67)
org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor.publishModuleEvent(EquinoxContainerAdaptor.java:102)
org.eclipse.osgi.container.Module.publishEvent(Module.java:461)
org.eclipse.osgi.container.Module.start(Module.java:452)
org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:402)
org.apache.felix.gogo.command.Basic.start(Basic.java:729)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.apache.felix.gogo.runtime.Reflective.invoke(Reflective.java:137)
So its seems like I should not instantiate the implementation in the service activator? That's how it seems to be done in this tutorial though.
You are getting a second instance of the component because you are explicitly creating it, on line 24 of ServiceActivator.java. This is revealed by the first stack trace that you posted.
Simply remove that line of code, and everything will be fine.
In fact you probably don't need ServiceActivator at all. I assume that it is the BundleActivator for your bundle? You do not need to write activators when using DS, because anything you can do in an activator can be done in a DS component, and much more besides. In fact my general recommendation is to never write bundle activators.
Neil has found the answer, let me just add a few details:
As Neil said, a service activator is not needed, despite what suggests the tutorial I linked to in my question. Just delete it.
Obviously, also remove the Bundle-Activator: line from bnd.bnd otherwise you will get a Bundle-Activator not found on the bundle class path nor in imports error when deploying.
In place of the service activator, use that "DS" thing Neil talks about. It means Declarative Services, and is an OSGi technology that works with annotations. To use it, just add a service = instruction in the #Component annotation of your implementation class, with the implemented service (API)'s interface as a value. Example:
#Component(
service = TranslationService.class,
immediate = true,
configurationPid = "my.TranslationConfiguration"
)
public class TranslationServiceImpl implements TranslationService {
I am trying to use Mockito like this :
Mockito.when(Mockito.any(ObjectMapper.class).readValue(Mockito.any(BufferedReader.class),Mockito.any(Class.class))).thenReturn(new Person("1","abc"));
This is from Jackson library .
public <T> T readValue(Reader src, Class<T> valueType)
The reason I am doing it is because the time I reach this point of the code there are a ton of objects which were created. Mocking on every step would take time.
Any reason why I am getting NPE when code reaches this mockito statement?
Stack Trace :
java.lang.NullPointerException
at com.prashant.flax.ShellTest.givenDirectoryHasFiles(ShellTest.java:139)
at com.prashant.flax.ShellTest.testExecute(ShellTest.java:61)
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:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
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)
As you can see it is in a given method(this method only has this piece of code) , so I can see while debugging, it reaches over there and crashes.
As Oliver mentioned in the comments, you can't apply when to happen to all objects. Mockito works via subclassing, so you have to create a mock instance using mock, spy, or a #Mock or #Spy annotation; customize the behavior; and then install the mock using dependency injection or other similar tricks.
As to why this happens, the return value for any() actually is null; matchers like any are only supposed to be used as arguments to when and verify, and Mockito can't produce a specialized instance of Class that represents "any Class", so Mockito returns a dummy value (null) and stores data on a specialized stack of argument matchers. Though Mockito has better error messages to alert you to this situation, your code NPEs before Mockito can give you a proper exception with usage examples.
For more about matcher return values and the stack, see my other SO answer on "How do Mockito matchers work?".
To extend on what #jeff-bowman said in his answer, any() returns null, so if you need something that doesn't return null, you can try this:
/**
* never returns null
*/
private inline fun <reified T> any(type: Class<T>): T = Mockito.any(type)
/**
* returns null
*/
private inline fun <reified T> any(): T = Mockito.any<T>()
For me the actual problem was that I was trying to mock a spy. When mocking a spy you have to use the doReturn or doAnswer methods. Otherwise the method of the spy will be actually called while trying to mock it and unexpected behavior can happen. E.g. when calling when with any(), any() will just return null. So it is likely that you will get an NullPointerException.
Here is a full example that demonstrates the bahavior:
package com.company;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
public class SpyTest {
public class Controller {
public String method(String arg) {
return arg.substring(0, 1);
}
}
#Test
public void withMockTest() {
Controller controllerMocked = mock(Controller.class);
when(controllerMocked.method(anyString())).thenReturn("42");
assertEquals("42", controllerMocked.method("FOO"));
}
#Test(expected = NullPointerException.class)
public void withSpyWhenThenReturnBreakingBecauseMethodToBeMockedIsActuallyBeingCalled() {
Controller controllerSpied = spy(new Controller());
when(controllerSpied.method(any())).thenReturn("42");
}
#Test
public void withSpyDoReturnWhen() {
Controller controllerSpied = spy(new Controller());
doReturn("42").when(controllerSpied).method(any());
assertEquals("42", controllerSpied.method("FOO"));
}
}
I'm new to Groovy, so it's likely I am doing something wrong. I had written a configuration to be taken in by ConfigSlurper. But something goes wrong when I actually try to parse it. My code is as follows:
class CharacterMap {
public static final String CHARACTER_CONFIGURATION = 'location'
static Map<String,String> characterMap = null
public static String ASCIIize(String input)
{
if (!characterMap)
{
def property = System.getProperty( CHARACTER_CONFIGURATION )
ConfigObject config = null
if( property ) {
ConfigSlurper cs = new ConfigSlurper()
File file = new File( property )
URL location = file.toURL()
config = cs.parse(location)
}
if (config)
{
characterMap = config.characters
}
else
{
getAnonymousLogger().logp WARNING, getClass().name, 'constructor',
"Server configuration groovy file not configured with system property ${CHARACTER_CONFIGURATION}"
return input
}
}
for (String key: characterMap.keySet())
{
if (input.contains(key))
{
input = input.replace(key, characterMap.get(key))
}
}
return input
}
public static void main(String[] args)
{
print ASCIIize(args[0])
}
}
When it gets to calling the parse method it complains Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: groovy.util.ConfigSlurper.parse() is applicable for argument types: (CharacterMap, java.net.URL)
As you can see, I am only passing in one argument, which was declared to be a URL. Since all the methods of the class are static and no constructor is referenced anywhere, it's kind of bizarre that an instance is being created at all, and more bizarre still that it's being passed into the parse method. I've read other people on Stack Overflow getting MissingMethodException (though usually related to closures rather than superfluous arguments), and it being blamed on Eclipse. I am running this in IntelliJ rather than Eclipse.
EDIT: In response to the comment below the groovy version is 1.8.6. Here is the stack-trace:
Exception in thread "main" groovy.lang.MissingMethodException: No
signature of method: groovy.util.ConfigSlurper.parse() is applicable
for argument types: (CharacterMap, java.net.URL) values:
[CharacterMap#34374a16, file:/C:/Program Files
(x86)/JetBrains/IntelliJ IDEA Community Edition
11.1.2/UCP/config/CharacterMap.groovy]
Possible solutions: parse(java.net.URL), parse(groovy.lang.Script,
java.net.URL), parse(groovy.lang.Script), parse(java.lang.Class),
parse(java.lang.String), parse(java.util.Properties)
at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
at
org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:78)
at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
at groovy.util.ConfigSlurper.parse(ConfigSlurper.groovy:148) at
groovy.util.ConfigSlurper$parse.call(Unknown Source) at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
at ucp.cms.search.CharacterMap.ASCIIize(CharacterMap.groovy:26) at
ucp.cms.search.CharacterMap.main(CharacterMap.groovy:51) at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601) at
com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Process finished with exit code 1