Android: mock Resources.openRawResource(int) - android

I'm trying to test some code that makes the call context.getResources().openRawResource(rawResourceId) (docs), where the resource is a text file to be read from.
My test class extends AndroidTestCase.
How would I be able to mock this call to return whatever file contents I want?

Assuming your able to set the Context of the code you're testing, you can do this by creating the following two classes (I tend to make them private classes within my test class because they contain test specific information):
private class mMockContext extends MockContext {
#Override
public Resources getResources() {
return new mMockResources();
}
}
private class mMockResources extends MockResources {
#Override
public InputStream openRawResource(int id) {
String fileContents = "line one\n" +
"line two\n" +
"line three";
return new ByteArrayInputStream(fileContents.getBytes());
}
}
Then, when you're creating your class to be tested, pass it the mMockContext class in place of the Context.

Related

what is the difference between "this" and "xxx.this" in android

example:
Why can I write like that MainActivity.this.getContentResolve();
but can not write like that this.getContentResolve(); in MainActivity.java
If you need to access instance of enclosing class from inner class you need to make declaration like this - ClassName.this.anyClassMethod();
For more info read this article Nested Classes
This syntax becomes relevant when using inner classes.
public class A {
String str = "A";
public class B {
String str = "B";
public String getStr() {
return A.this.str; //returns A
}
}
}
It's long described but i think your question is related to anonymous class.
When you are inside class and want to refer to the current object of the class you can use this for example:
public class MyActivity extends Activity{
int foo;
public Test(int _foo){
this.foo = _foo;
}
}
but when you want to refer to the current class object from anonymous class inside it you should use class.this for example:
MyActivity.this
Full example for Inner Class:
public class Test {
int foo = 1;
public class InnerTest {
public String getFoo() {
return Test.this.foo;
}
}
}
Why can I write like that MainActivity.this.getContentResolve() but
can not write like that this.getContentResolve()?
Because your trying to access the context of outer class (MainActivity) in the inner class. we use TheActivityClassName.this in the inner class to access the outer TheActivityClassName class’s context.
When we are accessing the activity context in inner class we need a reference to the activity class name so we pass it like MainActivity.this
and when we need it in the class then we can reference it simply like this.something
You should have a look here to get good grasp on what context is actually
Hope it helps
There is no difference if you are calling getContentResolver() from any direct method of the activity. You can write both MainActivity.this.getContentResolver(); and this.getContentResolver(); as well as simply getContentResolver() with the same effect. In this case, the this keyword refers to the current instance of the MainActivity.
However, if you are within an inner class or inside an implementation of an interface/abstract method inside the MainActivity, then this will refer to an instance of the inner class or the interface you are implementing. In that case, you have to call MainActivity.this to get access to the instance of the MainActivity.

android passing data from class to activity

I have been looking for a long time for a simple way to pass data (string type) from class to activity.
I found some tutorials about passing data from activity to class but is it possible to do the opposite, passing data from class to activity ?
if you import the class in your activity (which is also a class by the way) you can easily access the classes attributes.
example: MyClass.java
package edu.user.yourappname;
public class MyClass {
public string infoToPass = "whatever";
}
MyActivity.java
package edu.user.yourappname;
import edu.user.yourappname.MyClass
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
String myString = MyClass.infoToPass;
}
}
i have no IDE to type this in atm it might contain some errors :S but i hope you get the idea.
if you need more specific help you have to provide a code sample.
also, what do you want to achieve exactly? maybie there's a different approach.
cheers!
Create Interface and implement that in your activity. Pass the activity instance in your class and and call that instance with interface method whenever you like.
To be more clear, create an interface and use it as following:
public interface SomeInterface{
public void passValue(String value);
}
public SomeActivity extends Activity implements SomeInterface{
// place any code you want in your activity, onCreate, onResume, etc.
private void someMethod(){
// Wherever in your activity, initialize your class with your activity.
SomeClass someClass = new SomeClass(this);
someClass.someMethod();
}
public void passValue(String value){
// do whatever you want with your value
}
}
public class SomeClass{
private SomeInterface someInterfaceInstance;
public SomeClass(SomeInterface someInterfaceInstance){
this.someInterfaceInstance = someInterfaceInstance;
}
public void someMethod(){
// Some code...
someInterfaceInstance.passValue("Hello World!");
// Some more code...
}
}
Here is a easy way of doing it -
By defining static variables
In your class, make the String whose value you want to pass public static like this -
public static String pass;
And then in you activity, you can directly access it since it's a public variable like this -
String receive = className.pass;

How to determine if Android Application is started with JUnit testing instrumentation?

I need to determine in runtime from code if the application is run under TestInstrumentation.
I could initialize the test environment with some env/system variable, but Eclipse ADK launch configuration would not allow me to do that.
Default Android system properties and environment do not to have any data about it. Moreover, they are identically same, whether the application is started regularly or under test.
This one could be a solution: Is it possible to find out if an Android application runs as part of an instrumentation test but since I do not test activities, all proposed methods there won't work. The ActivityManager.isRunningInTestHarness() method uses this under the hood:
SystemProperties.getBoolean("ro.test_harness")
which always returns false in my case. (To work with the hidden android.os.SystemProperties class I use reflection).
What else can I do to try to determine from inside the application if it's under test?
I have found one hacky solution: out of the application one can try to load a class from the testing package. The appication classloader surprisingly can load classes by name from the testing project if it was run under test. In other case the class is not found.
private static boolean isTestMode() {
boolean result;
try {
application.getClassLoader().loadClass("foo.bar.test.SomeTest");
// alternatively (see the comment below):
// Class.forName("foo.bar.test.SomeTest");
result = true;
} catch (final Exception e) {
result = false;
}
return result;
}
I admit this is not elegant but it works. Will be grateful for the proper solution.
The isTestMode() solution did not work for me on Android Studio 1.2.1.1. Almighty Krzysztof from our company tweaked your method by using:
Class.forName("foo.bar.test.SomeTest");
instead of getClassLoader(). Thanks for Krzysztof!
We created a solution to pass parameters to the MainActivity and use it inside the onCreate method, enabling you to define how the Activity will be created.
In MainActivity class, we created some constants, which could also be an enum. We created a static attribute too.
public class MainActivity {
public static final int APPLICATION_MODE = 5;
public static final int UNIT_TEST_MODE = 10;
public static final int OTHER_MODE = 15;
public static int activityMode = APPLICATION_MODE;
(...)
#Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
switch (activityMode) {
case OTHER_MODE:
(...)
break;
case UNIT_TEST_MODE:
Log.d(TAG, "Is in Test Mode!");
break;
case APPLICATION_MODE:
(...)
break;
}
(...)
}
(...)
}
We made MainActivityTest class abstract, created a setApplicationMode and called this method inside the setUp() method, before calling the super.setUp() method.
public abstract class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
protected void setUp() throws Exception {
setApplicationMode(); // <=====
super.setUp();
getActivity();
(...)
}
(...)
public void setApplicationMode() {
MainActivity.activityMode = MainActivity.UNIT_TEST_MODE;
}
}
All other test classes inherit from MainActivityTest, if we want it to have another behaviour, we can simply override the setApplicationMode method.
public class OtherMainActivityTest extends MainActivityTest {
(...)
#Override
public void setApplicationMode() {
MainActivity.activityMode = MainActivity.OTHER_MODE;
}
}
The user nathan-almeida is the friend that is co-author of this solution.

Using Resources in Exceptions

I have an app that uses custom Exceptions, such as this:
public class SomeException extends Exception{
private int iCode;
private String iMessage;
public SomeException(){
iCode = 201;
iMessage = **//Get the localized string R.string.error_201??**
}
#Override
public String getMessage() {
return iMessage;
}
#Override
public int getCode() {
return iCode;
}
}
Obviously, I want lo localize the error message. I have possible solutions but non of them satisfy me.
1) Pass "Context" to the constructor, and do ctx.getString(R.string.error_201)
--> Fail, as this Exceptions are sometimes thrown from MODEL classes, so they don't have a Context
2) Pass "Context" when retriveing the message in getMessage() function,
--> Fail, It's necesary to override the super method, to work as all other Exceptions.
Solution I have now: All activities in my app have this onCreate:
public void onCreate(...){
Utils.RESOURCES = getResources();
...
}
Very dirty code... I don't like the solution. My question is then,: is there a way to access the resources without the Context? And most important, How would an application such as mine solve this problem?
What about
public class MyException extends Exception {
private int iCode;
public MyException(int code) {
this.iCode = code;
}
#Override
public String getMessage() {
return "MyException code " + String.valueOf(iCode);
}
public String getLocalizedMessage(Context ctx) {
String message;
if (iCode == 201)
message = ctx.getString(R.string.error_201);
else if (iCode == 202)
message = ctx.getString(R.string.error_202);
// ...
}
}
Even if there was way to access context in different way, you should not do it. If you need to emit exceptions where you cannot pass Context, you should be able to access context before you display such error. I cannot see reason why you should create localized error messages from constructor. You can log to logcat not localized versions if you need. And where you want to display something in UI, you should have context at hand.
You can access only system wide resources without Context.
You need a Context, so I would suggest You to get it as soon as possible, and make it available through a static method or variable. You do the same thing in every Activity, but there is a cleaner method. You should make a custom Application, and override its onCreate() to make the resources public:
public class App extends Application {
private static Resources myResources;
#Override
public void onCreate() {
myResources = getBaseContext().getResources();
super.onCreate();
}
public static Resources getMyResources(){
return myResources;
}
}
The other thing you have to do is to set the Application in your manifest:
<application
android:name="{your_package}.App"
...
Now you can access the resources in all of your Activity without any preparation. Your custom Exception class could also use the externalized resources.

android - how to create a reusable function?

In my android project, I have many activities and some of them already extend other stuff like map activity or BroadcastReceiver.
How do I create a function that I can call from any activity, because I don't want to have to repeat any code in multiple activities.
thanks.
If I have useful functions that perform little helpful tasks that I want to invoke from several Activities, I create a class called Util and park them in there. I make them static so that I don't need to allocate any objects.
Here is an example of part of one such class I wrote:
public final class Util {
public final static int KIBI = 1024;
public final static int BYTE = 1;
public final static int KIBIBYTE = KIBI * BYTE;
/**
* Private constructor to prevent instantiation
*/
private Util() {}
public static String getTimeStampNow() {
Time time = new Time();
time.setToNow();
return time.format3339(false);
}
}
To use these constants and methods, I can access them from the class name, rather than any object:
int fileSize = 10 * Util.KIBIBYTE;
String timestamp = Util.getTimeStampNow();
There's more to the class than this, but you get the idea.
You can extend the Application class, then in your activities call the getApplication method and cast it to your application class in order to call the method.
You do this by creating a class that extends android.app.Application:
package your.package.name.here;
import android.app.Application;
public class MyApplication extends Application {
public void doSomething(){
//Do something here
}
}
In your manifest you must then find the tag and add the android:name="MyApplication" attribute.
In your activity class you can then call the function by doing:
((MyApplication)getApplication()).doSomething();
There are other ways of doing something similar, but this is one of the ways. The documentation even states that a static singleton is a better choice in most cases. The Application documentation is available at: http://developer.android.com/reference/android/app/Application.html
You could create a static method or an object that contains this method.
You can create a class extending Activity, and then make sure your real activities are subclasses of that activity, instead of the usual built-in one. Simply define your common code in this parent activity.
Shachar
Create a new Java class BaseActivity with abstract Modifiers and extends it with AppCompatActivity.
Move all your methods under Java class BaseActivity.
package com.example.madbox;
public abstract class BaseActivity extends AppCompatActivity {
protected void YourClass() {
}
}
Extends your Activities with BaseActivity but not AppCompatActivity.

Categories

Resources