how to access internal properties from java test code - java

I've got some class with property marked as internal.
Then I try to set that property from test code which is in java.
How can I access those properties? test code and class code are in the same package.
example:
class MainActivity : AppCompatActivity() {
interal var someProperty = "test"
}
test code:
#Test
public void firstStartTest() {
val activity = MainActivity()
activity.setSomeProperty("something") //does not compile
}
Android Studio is suggesting activity.setSomeProperty$production_sources_for_module_app();
but this also does not compile.

Both classes (MainActivity and test class) must be in one module. This is a module definition:
More specifically, a module is a set of Kotlin files compiled together:
an IntelliJ IDEA module;
a Maven or Gradle project;
a set of files
compiled with one invocation of the Ant task.
https://kotlinlang.org/docs/reference/visibility-modifiers.html
It means, check your project structure.

add #JvmField annotation.
It treats variable as java protected

There are two ways of doing this:
Make the property protected. Note on how Java & Kotlin treat protected differently. In Java it's possible that other classes in the same package access protected members. Thus your test class (in Java) can access it.
Access the property via its ugly name. It should be sort of like activity.setSomeProperty$production_.... Make use the autocomplete. From the documentation:
Members of internal classes go through name mangling, to make it
harder to accidentally use them from Java and to allow overloading for
members with the same signature that don't see each other according to
Kotlin rules;

Related

Add an annotation to a class from a place other than class definition

I need to add an annotation to a class which is in a sperate dependency (in a separate jar) of the project that I am working on. I am wondering that can I do this in Java?
As an example, I need to add an annotation HisClass without touching the source code of HisClass.
public class HisClass{
// ...
}
So, that the above class should be look like below at the build time,
#MyAnnot ( me = MyClass.class )
public class HisClass{
// ...
}
There are many ways:
Write a compiler plugin for javac, and make it add the annotations. This will be quite difficult, as the plugin API has nearly no documentation.
2.(Maybe not possible) Inject the annotation after compiling. Add an extra buildstep after compiling and use a library like ASM to add this annotation to the classfile.

How to reference a class in an external JAR in Eclipse?

I would like to reference a class Bag in a JAR file, but Eclipse is telling me that Bag cannot be resolved to a type. I have added the JAR in which Bag is defined to the classpath for the project, but the error is still there. What am I doing wrong?
I think you can't do that, because the Bag class in algs4.jar is inside the default package.
Before J2SE 1.4, we still can import classes from the default package using a syntax like this:
import Unfinished;
But from J2SE 1.5, that's no longer allowed. So if we want to access a default package class from within a packaged class requires moving the default package class into a package of its own. Read here for more detail explanation :
How to access java-classes in the default-package?
Some options you can choose :
Access the class via reflection or some other indirect method. But it is a little bit hard, something like this :
Class fooClass = Class.forName("FooBar");
Method fooMethod = fooClass.getMethod("fooMethod", new Class[] { String.class });
String fooReturned = fooMethod.invoke(fooClass.newInstance(), new String("I did it"));
If you own the source code of that jar library, you need to put it in properly package and wrap it again as a new jar library.
You may need to either fully qualify the Bag class, or import it.

Is there any way to mock JNI methods in my android project to do Junit testing?

Hi I need to write Junit tests for an Android project but it has JNI methods as it uses webkit.Is there any way I can test those android methods(I dont want to test JNI methods).
Its like:
public void androidMethod(){
//some android code
nativeInit(); //how do I mock such methods?
//some code again
}
I have tried powermock,easymock,roboelectric but wasnt successful.Please help me.
I yesterday found I could solve this with Mockito (I didn't try powermock or easymock). Assuming your class is class C, my solution is:
C c=spy(new C);
doNothing().when(c).nativeInit();
c.androidMethod()
verify(c).nativeInit();
This does, of course, require that nativeInit is visible to the test.
Similar Problem
I had the same problem event though I was already using mockito in JUnit tests under src/test. Once I added tests under src/androidTest I started having issues, including this crash:
Mockito cannot mock/spy because :
- final class
And after making the class open, manually, I still got crashes in the JNI layer as it tried to load the *.so library (which wouldn't happen if mocks were working properly).
Working Solution
Instead, what I had to do was open the class for testing purposes using Kotlin's all-open plugin. The process is also explained well in this recent medium post but it boils down to the following four simple changes that are also modeled in one of the architecture components sample apps:
1. Make these additions to build.gradle:
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}"
}
}
apply plugin: "kotlin-allopen"
allOpen {
// marker for classes that we want to be able to extend in debug builds
annotation 'com.your.package.name.OpenClass'
}
2. Add the corresponding annotations in the debug flavor. For example: app/src/debug/java/com/your/package/name/OpenForTesting.kt
package com.your.package.name
#Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class OpenClass
#OpenClass
#Target(AnnotationTarget.CLASS)
annotation class OpenForTesting
3. Add the corresponding annotation in the release flavor. For example: app/src/release/java/com/your/package/name/OpenForTesting.kt
package com.your.package.name
#Target(AnnotationTarget.CLASS)
annotation class OpenForTesting
4. Add the #OpenForTesting annotation to the class that needs to be mocked
package com.your.package.name
#OpenForTesting
class JniClassOfVictory {
...
external fun nativeInit()
...
companion object {
init {
System.loadLibrary("victoryeveryday")
}
}
}
The result is a flexible way to mark classes as open without actually making them open in release builds. Of course, this is because the #OpenForTesting annotation that we created in release is not marked with #OpenClass but the same annotation in debug is marked with #OpenClass. In build.gradle we designated that annotation as the signal to the kotlin-allopen plugin. So any class annotated with #OpenForTesting will be made open at compile-time but only on Debug builds.

Java Adding External Library failed when Self-defined Package Exists

Recently I have encountered some problem which seems a little strange to me.
In order to use some predefined class, I imported two .jar files say foo.jar and bar.jar(Both were written by others)
And my source code is like the following:
package jerry.deque
public class Deque {
.....
.....
Foo item = new Foo(); //Already defined in the foo.jar
.....
}
I added the external library exactly as what How to Import a Jar in Eclipse
did. But when I tried to use the class defined in foo.jar Eclipse shows me that "Foo can't be resolved to a type".
I spent a lot of time to fix this problem and finally succeeded after I removed
the clause: "package jerry.deque" at the beginning of my class file.
I think this is weird because just a few days ago when I was doing some Android development, I followed the same way to add a Twitter API library. And it works fine even when I declared "package jerry.search_twittes" at the beginning of my .java
file. I'm confused by this problem and couldn't figure out what's going wrong. Could someone help me to explain it in detail? Thanks very much.
Check that Foo is same package as Deque class. If they are not same
package, you need to import Foo class in Deque class.
For example,
package jerry.deque;
import packagename.foo; // packagename.foo
public class Deque {
.....
.....
Foo item = new Foo(); //Already defined in the foo.jar
.....
}
Added Explanation
I want you to check access modifier of Foo class carefully.
There are 2 access level for top level(class) access control . These
are public, or package-private (no explicit modifier).
Your Foo class is under default package(not specified package)and may be no explicit access modifier. Hope so! Then, all classes under default package can access to Foo class. That's why when you remove package jerry.deque clause, it works.
Similarly, I want you to check Android development java code in which it works fine even when you declared "package jerry.search_twittes". In that case, classes inside Twitter API library's access modifier is public.So you can access it from anywhere.
For more information you can read this.Is this information helpful???
Foo is in default package. Classes from default package cannot be imported directly.
So when you remove the package declaration in your code, you don't get the error.
You can look for reflection api or write a proxy in the default package for that class.

Scala trouble accessing Java methods

So, I have something written in Java, and I want to extend it in Scala... The issue I'm running into is that Scala isn't seeing methods I need.
Here is how it's set up:
Player extends Mob, and Mob extends Entity.
I need to access a method in Player that isn't defined in Mob or Entity, but Scala doesn't think it exists even though Java does.
It can see methods defined by Mob and Entity just fine. Also, all the methods I'm talking about are non-static.
So, am I doing something wrong, or is this a limitation imposed by Scala?
Edit --
Here is the relevant code:
package test
import rsca.gs.model.Player
object Test {
def handle(p:Player): Unit = {
p.getActionSender().sendTeleBubble(0, 0, false);
}
}
Player class:
package rsca.gs.model;
// imports
public final class Player extends Mob {
// Implemented methods (not going to post them, as there are quite a few)
// Relevant code
private MiscPacketBuilder actionSender;
public MiscPacketBuilder getActionSender() {
return actionSender;
}
}
Error:
value getActionSender is not a member of rsca.gs.model.Player
I never encountered such problems, and you probably checked your configuration and everything else twice, so I would guess this is some Eclipse related build issue. You should try to build from the command line in order to see whether Scala or Eclipse is the problem.
Is it possible for you to run a test against the class just to see if you got the right one?
p.getClass.getMethods
... and if possible (may run into NPE) in order to find the source:
p.getClass.getProtectionDomain.getCodeSource.getLocation.getPath
When compiling the Scala class, do something like this:
scalac *.scala *.java
This way, Scala will look a the Java code to see what is available. If, however, the Java code is already compiled and provided as a jar file, just add it to the classpath used when compiling the Scala code.

Categories

Resources