Android mock Camera - java

Is it possible to mock the Android Camera class ?
#Override
public void setUp() {
_camera = Mockito.mock(Camera.class);
}
fails to generate a mock (ExceptionInitializerError in Mockito's createProxyClass).
Should I create some kind of wrapper around the Camera (not my favorite solution, would really like to just mock the class...)?
Or, should I use a different mock library then Mockito?
Hope somebody can point me in the right direction.
Complete stacktrace of ExceptionInitializerError
java.lang.ExceptionInInitializerError
at org.mockito.internal.creation.jmock.ClassImposterizer.createProxyClass(ClassImposterizer.java:85)
at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:62)
at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:56)
at org.mockito.internal.creation.CglibMockMaker.createMock(CglibMockMaker.java:23)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:51)
at org.mockito.Mockito.mock(Mockito.java:1243)
at org.mockito.Mockito.mock(Mockito.java:1120)
at com.cleancode.lifesaver.flashlight.test.FlashLightTests.setUp(FlashLightTests.java:20)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1661)
Caused by: java.lang.VerifyError: org/mockito/cglib/core/ReflectUtils
at org.mockito.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:167)
at org.mockito.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:217)
at org.mockito.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:117)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:109)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:105)
at org.mockito.cglib.proxy.Enhancer.<clinit>(Enhancer.java:70)
... 18 more

The answer is late but here is a mock camera example for Android.
You can set the VideoFileInputSource to mock camera from video file
textureVideoInputSource = new VideoFileInputSource(this, "mock_input_video.mp4");
or you can enable hardware camera for video stream.
textureVideoInputSource = new CameraTextureVideoInputSource(this);
You can find the complete sample project here.
https://github.com/muneikh/MockCamera

In your stacktrace, notice the substring ".CglibMockMaker": that's the problem here. CGLib doesn't work on android -- there's a plugin for Mockito specifically for android that uses dexmaker, which is like CGLib but works for dalvik. Just search for dexmaker mockito and you should be on the right path.
You still won't be able to mock Camera.open() (the static factory method), but you can refactor your code around that. What matters is that Camera is not a final class; the rest is just awkward plumbing for the test, which you should just accept as the tax for writing well-tested android apps.

I think the ExceptionInInitializerError exception is happening because Camera is only supposed to be instantiated through its static open() method, so some kind of static initialization is failing when Mockito tries to create a mock. It doesn't seem to be possible to work around that. Perhaps it expects to interact with hardware that isn't present in a test environment? You may be able to use PowerMock to mock it anyway, or you may just want to go with your stated alternative of a wrapper class with an interface.

Related

Can I mock Kotlin service into java Junit test

I'm currently writing Junit test with Mockito in java. But one microservice is written in Kotlin.
I try to mock the kotlin service, but it doesn't work as I excepted.
I plan to return a customize response inside the test, I checked it with debugger, instead of returning the response, it always runs into the kotlin function(getFile).
#Mock
private FileService fileservice; // this service written in Kotlin
#Before
public void setUp() {
Response respone = new Response(...);
when(fileservice.getFile(any())).thenReturn(response);
}
The best approach is to use mocking library designed for Kotlin, there is few options for this:
If still needed to stick to mockito, there is official mockito support for kotlin, more details here: https://github.com/mockito/mockito-kotlin
Also there is mockk library that specially designed for kotlin, and it better fits than mockito: https://mockk.io/
Also many java libraries using byte-code generated proxies like mockito does, while kotlin makes every class final by default, there is a kotlin plugin named all-open, which can make all needed classes open: https://kotlinlang.org/docs/all-open-plugin.html

JUnit 5, pass information from test class to extension

I am trying to write an extension for Junit5 similar to what I had for Junit4 but I am failing to grasp how to do that in the new (stateless) extension system.
The idea in the previous version was that user could pass information into extension class and hence change the way it behaved. Here is a pseudo snippet showing approximately what is used to do:
public void MyTest {
// here I can define different behaviour for my extension
#Rule MyCustomRule rule = MyCustomRule.of(Foo.class).withPackage(Bar.class.getPackage).alsoUse(Cookies.class);
#Test
public void someTest() {
// some test code already affected by the #Rule
// plus, user has access to that class and can use it, say, retrieve additional information
rule.grabInfoAboutStuff();
}
}
Now, I know how to operate JUnit 5 extension, what lifecycles to use etc. But I don't know how to give the test-writer the power to modify my extension's behaviour with JUnit5. Any pointers appreciated.
As of JUnit Jupiter 5.0.1, it is unfortunately not possible to pass parameters to an Extension programmatically like you could for rules in JUnit 4.
However, I am working on adding such support in JUnit Jupiter 5.1. You can follow the following issue if you like: https://github.com/junit-team/junit5/issues/497
In the interim, the only way to pass information to an extension is for the extension to support custom annotations and extract the user-supplied information from there. For example, I allow users to provide a custom SpEL expression in the #EnabledIf annotation in the Spring Framework, and my ExecutionCondition extension pulls the expression from the annotation using reflection.
followup on the (accepted) answer from Sam as in the meantime the referred bug has been implemented with junit 5.1
use #RegisterExtension
see https://junit.org/junit5/docs/current/user-guide/#extensions-registration-programmatic

Reflection error when creating a class using ByteBuddy on Google App Engine

I am trying to define a sublclass dynamically from a concrete class using ByteBuddy as follows
Class<? extends MyConcreteClass> dynamicType = new ByteBuddy()
.subclass(MyConcreteClass.class, ConstructorStrategy.Default.DEFAULT_CONSTRUCTOR)
.name(dynamicClassName)
.annotateType(MyConcreteClass.class.getDeclaredAnnotations())
.make()
.load(MyConcreteClass.class.getClassLoader())
.getLoaded();
This code works from within a JUnit test, but when I run it under Google App Engine, I get the following exception.
java.lang.IllegalStateException: Cannot access java.lang.reflect.Parameter#getModifiers
at net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$Dispatcher$ForJava8CapableVm.getParameterCount(ParameterList.java:261)
at net.bytebuddy.description.method.ParameterList$ForLoadedExecutable.size(ParameterList.java:157)
at net.bytebuddy.description.method.ParameterList$TypeSubstituting.size(ParameterList.java:582)
at net.bytebuddy.matcher.CollectionSizeMatcher.matches(CollectionSizeMatcher.java:34)
at net.bytebuddy.matcher.CollectionSizeMatcher.matches(CollectionSizeMatcher.java:13)
at net.bytebuddy.matcher.MethodParametersMatcher.matches(MethodParametersMatcher.java:32)
at net.bytebuddy.matcher.MethodParametersMatcher.matches(MethodParametersMatcher.java:13)
at net.bytebuddy.matcher.ElementMatcher$Junction$Conjunction.matches(ElementMatcher.java:101)
at net.bytebuddy.matcher.ElementMatcher$Junction$Conjunction.matches(ElementMatcher.java:101)
at net.bytebuddy.matcher.FilterableList$AbstractBase.filter(FilterableList.java:96)
at net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default$2.doExtractConstructors(ConstructorStrategy.java:82)
at net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default.extractConstructors(ConstructorStrategy.java:176)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.applyConstructorStrategy(SubclassDynamicTypeBuilder.java:185)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:162)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:155)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2559)
...
Caused by: java.lang.IllegalAccessException: Reflection is not allowed on public int java.lang.reflect.Executable.getParameterCount()
at com.google.appengine.tools.development.agent.runtime.Runtime.verifyWhiteListed(Runtime.java:90)
at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:125)
at net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$Dispatcher$ForJava8CapableVm.getParameterCount(ParameterList.java:259)
The exception is thrown while executing the method make().
Is there a way to make this work under the GAE?
That's a very random restriction and most definitely a bug on the GAE. Please report it.
As a background: Byte Buddy detects a JVM's version and offers features accordingly. In this case, it detects that the parameter API that was added with Java 8 exists and uses it. However, GAE seems to disallow its use via reflection.

Exception during PowerMock of HConnectionManager.class (HBase)

PowerMockito.mockStatic(HConnectionManager.class);
when(HConnectionManager.createConnection(configuration)).thenReturn(hConnection)
What are the ways to mock HBase related configuration files? As I get:
java.lang.ExceptionInInitializerError
at com.mapr.fs.ShimLoader.load(ShimLoader.java:214)
at org.apache.hadoop.conf.CoreDefaultProperties.<clinit>(CoreDefaultProperties.java:60)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:274)
at org.apache.hadoop.conf.Configuration.getClassByNameOrNull(Configuration.java:1857)
at org.apache.hadoop.conf.Configuration.getProperties(Configuration.java:2072)
at org.apache.hadoop.conf.Configuration.loadResource(Configuration.java:2282)
at org.apache.hadoop.conf.Configuration.loadResources(Configuration.java:2234)
at org.apache.hadoop.conf.Configuration.getProps(Configuration.java:2151)
at org.apache.hadoop.conf.Configuration.get(Configuration.java:871)
at org.apache.hadoop.conf.Configuration.getTrimmed(Configuration.java:890)
at org.apache.hadoop.conf.Configuration.getBoolean(Configuration.java:1291)
at org.apache.hadoop.hbase.HBaseConfiguration.checkDefaultsVersion(HBaseConfiguration.java:71)
at org.apache.hadoop.hbase.HBaseConfiguration.addHbaseResources(HBaseConfiguration.java:107)
at org.apache.hadoop.hbase.HBaseConfiguration.create(HBaseConfiguration.java:118)
at org.apache.hadoop.hbase.client.HConnectionManager.<clinit>(HConnectionManager.java:266)
at sun.reflect.GeneratedSerializationConstructorAccessor35.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:45)
at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)
at org.mockito.internal.creation.instance.ObjenesisInstantiator.newInstance(ObjenesisInstantiator.java:14)
at org.powermock.api.mockito.repackaged.ClassImposterizer.createProxy(ClassImposterizer.java:143)
at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:58)
at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:49)
at org.powermock.api.mockito.repackaged.CglibMockMaker.createMock(CglibMockMaker.java:24)
at org.powermock.api.mockito.internal.mockmaker.PowerMockMaker.createMock(PowerMockMaker.java:46)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59)
at org.mockito.Mockito.mock(Mockito.java:1285)
at org.mockito.Mockito.mock(Mockito.java:1163)
Not a direct solution, but a reasonable workaround: I assume, you want to use PowerMock to test your code, that has to make this static call, to then use the result coming back from it.
So, instead of "directly" making this static call, you create a wrapper around this functionality, like:
interface ConnectionProvider {
public HConneciotn createConnection(configuration);
and a corresponding class that implements that method (by actually makes the static call).
Now you can change your other production code to work with your that new interface; and now, all your client code can be tested without the need to user PowerMokito ... because there is no more static call.
Of course, you might want to use PowerMokito to ensure that your new wrapper implementation is doing exactly what you expect it to do.
Use #SuppressStaticInitializationFor("org.apache.hadoop.conf.CoreDefaultProperties") to suppress static initialisation of the org.apache.hadoop.conf.CoreDefaultPropertiesclass. More information you may find in PowerMock documentation.
If you've just started write your application then, the better way will be create a class wrapper which will encapsulate static call and the wrapper in your system. There is a good principal: don't mock what you don't own.
And for the wrapper you may write an integration test that will test that wrapper works as you expected and you system expected.

Testing SQLiteOpenHelper subclass with JUnit

I am writing JUnit tests for my Android app. I have read through the Android developer resources (testing fundamentals, Spinner example test, etc.). Now I want to test my SQLiteOpenHelper subclass independently of the Activities which use it. My idea is to extend ActivityInstrumentationTestCase2<Activity>. Is it okay to simply use Activity as the generic parameter or do I need a subclass? Also, am I headed in the right direction here, or is there a better way to test my SQLiteOpenHelper subclass?
I was looking for an answer to exactly this problem, and found this link as well as another interesting related question here:
Android JUnit test for SQLiteOpenHelper
The accepted answer by #Pietro shows some simple code, using a basic AndroidTestCase, which will help directly to answer the question.
public class DatabaseTest extends AndroidTestCase {
private MyDatabase db;
public void setUp(){
RenamingDelegatingContext context
= new RenamingDelegatingContext(getContext(), "test_");
db = new MyDatabase(context);
}
public void testAddEntry(){
// Here I have my new database which is not connected to the standard database of the App
}
public void tearDown() throws Exception{
db.close();
super.tearDown();
}
}
I was happy at how simple it looks. In my case I'm new to Android testing, so even the simple stuff seems difficult at the moment.
But the interesting part which is key, is using the RenamingDelegatingContext class as your "context" instead of just using a normal context. This seems to build on the comments made by #Jens.
This class wraps a given context and delegates most operations to that context. The useful part is that it performs database and file operations with a renamed database/file name (see documentation online).
This allows your TEST code to use an actual different instance of the database to your PRODUCTION code - at least in my case this is going to be useful.
Here is another related post where the accepted answer says pretty much the same thing:
Testing database on Android: ProviderTestCase2 or RenamingDelegatingContext?
Some useful tips in there about using ContentProvider instead (but that's a different issue for another day).
following link talk about testing in android:
http://developer.android.com/tools/testing/testing_android.html
may be you have already seen it just posting it in case you have missed going through it.. it is a very good resource to learn about junit in android...
For testing with Android Studio,
You should use MockContext instead of RenamingDelegatingContext.
If you use RenamingDelegatingContext, You would get context as null.
For AndroidTestCase, getContext() would return null. And for InstrumentationTestCase, getInstrumentation().getContext() would return null.
For further information, see this answer. https://stackoverflow.com/a/29063736/1020456

Categories

Resources