hope you can help me ...
tl:dr
How can i write JUnit Tests which will NOT use the classes IsolatedContext and MockContentResolver ? I want to affect the REAL content Provider and not the Mock Database.
General
I have to write JUnit Tests for a special ContentProvider at work.
This Content Provider is connected to some different Hardware and sets there some values. I must check the Hardware Values AND the Values of the Content Provider Database.
Construct
-> ContentProvider -> Hardware Interface -> Hardware -> HardwareInterface-> ContentProvider
Code
public class DataLayerTests extends ProviderTestCase2<DataLayer> {
private static final String TAG = DataLayerTests.class.getSimpleName();
MockContentResolver mMockResolver;
public DataLayerTests() {
super(DataLayer.class, Constants.DATA_LAYER_AUTHORITY);
}
#Override
protected void setUp() throws Exception {
super.setUp();
Log.d(TAG, "setUp: ");
mMockResolver = getMockContentResolver();
}
#Override
protected void tearDown() throws Exception {
super.tearDown();
Log.d(TAG, "tearDown:");
}
public void testActiveUserInsert__inserts_a_valid_record() {
Uri uri = mMockResolver.insert(ActiveUserContract.CONTENT_URI, getFullActiveUserContentValues());
assertEquals(1L, ContentUris.parseId(uri));
}}
The real Database should be affected as well as the Real ContentRescolver should be used.
How could i arcive this ?
You can use Robolectric to test the real content provider, affecting a real sqlite database.
Robolectric is an implementation of the Android framework that can be run in any JVM, and thus can be used for tests.
Please note that the sqlite database will live in a temp folder on your computer and not on a phone or emulator.
If you want the tests to happen inside a real phone, you should look into Instrumented tests
Related
I need to create an Android application to set carrier configuration(VoLte e.g.). The application should fetch configs from our Back-End and apply them on the phone.
In Android documentation I found the following article: This article says, that I can create my own application and override CarrierService.
public class SampleCarrierConfigService extends CarrierService {
private static final String TAG = "SampleCarrierConfigService";
public SampleCarrierConfigService() {
Log.d(TAG, "Service created");
}
#Override
public PersistableBundle onLoadConfig(CarrierIdentifier id) {
Log.d(TAG, "Config being fetched");
PersistableBundle config = new PersistableBundle();
config.putBoolean(
CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL, true);
config.putBoolean(
CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, false);
config.putInt(CarrierConfigManager.KEY_VOLTE_REPLACEMENT_RAT_INT, 6);
// Check CarrierIdentifier and add more config if needed…
return config;
}
}
I created an app with this service, but the method onLoadConfig(CarrierIdentifier id) is never called by the system.
So what I want from the system to call my overridden method, not system's. What should I do?
I found your question when researching how to do something similar.
In the article you linked it says:
The carrier app in question must be signed with the same certificate found on the SIM card, as documented in UICC Carrier Privileges.
Since we can't get the certificate from your carrier (they will never give it to you) I think we can't implement our own flavour sadly :-(
public class ConnectionPointTest {
#Test
public void testMockito() throws IOException {
DataInputStream dataInputStream = mock(DataInputStream.class);
when(dataInputStream.readUTF()).thenReturn("Test");
new JustTest(dataInputStream).doTest();
}
public class JustTest {
DataInputStream dataInputStream;
public JustTest(DataInputStream dataInputStream) {
this.dataInputStream = dataInputStream;
}
public void doTest() throws IOException {
String s = dataInputStream.readUTF();
System.out.println(s);
}
}
}
I implement JUnit testing + Mockito in the project. Then I try to mock my DataInpuStream, I have an exeption at this code :
when(dataInputStream.readUTF()).thenReturn("Test");
P.S. class JustTest is only for show you what I want to mock.
There is exeption:
java.lang.NullPointerException
at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:337)
at java.io.DataInputStream.readUTF(DataInputStream.java:589)
at java.io.DataInputStream.readUTF(DataInputStream.java:564)
...
You are trying to mock a final method:
public final String readUTF() throws IOException {
return readUTF(this);
}
Mockito (v2.x) supports this but it requires additional configuration. More details in the docs:
Mocking of final classes and methods is an incubating, opt-in feature. It uses a combination of Java agent instrumentation and subclassing in order to enable mockability of these types. As this works differently to our current mechanism and this one has different limitations and as we want to gather experience and user feedback, this feature had to be explicitly activated to be available ; it can be done via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line:
mock-maker-inline
So, create a file named org.mockito.plugins.MockMaker with this content:
mock-maker-inline
Place this file in a folder named mockito-extensions on your test classpath (if you are using Maven just create this folder in src/test/resources)
Re run your test.
With this configuration in place I have successful run your test with:
JUnit 4.12
Mockito 2.7.19
We are using the Ereza CustomActivityOnCrash library to handle unexpected issues with our android app. It's activity offers some debug output which we enable in develop and test builds but disable on production builds. In addition we want to log that information about crash details (log entries, stack trace, error details) in background.
CustomActivityOnCrash offers to call event listeners which sounds convenient. I wanted to implement the interface in our logging service, however I do not understand how I can access the existing information in the crash activity that way. Which puzzles me, cause isn't that a natural expectation?
Basically I need to access public methods of an android activity object from an event listener method that does not get handed over anything. How can I access that activity in the handler method? And how can I get the intent of the activity leading to the crash which is the argument the crash activity expects in those public methods it offers to access the existing information it offers? The examples given in the libraries documentation and those I could find on the internet are trivial, they only dump example strings, not the actual data collected by the library.
This all sounds counter intuitive to me. Which is why I think I generally miss something here. Maybe someone has a short hint for me to bring me on track again. Thanks!
Here is the basics of the LogService implementation I imagine:
...
import cat.ereza.customactivityoncrash.CustomActivityOnCrash;
...
public class LogService
implements CustomActivityOnCrash.EventListener {
private static LogService instance;
...
public void log(LogLevel level, String message) {
....
}
public void logCrashDetails(String activityLog, String stackTrace, String errorDetails) {
String message = String.format(
"--- CRASH REPORT ---\n\n-- Activity log:\n%s\n\n- Stack trace:\n%s\n\nError details:\n%s",
activityLog,
stackTrace,
errorDetails);
log(LogLevel.ERROR, message);
}
....
// CustomActivityOnCrash EventListener interface
#Override
public void onLaunchErrorActivity() {
log(LogLevel.INFO, "COAC: app crashed");
logCrashDetails(
// CustomActivityOnCrash.getActivityLogFromIntent(...some intent...),
// CustomActivityOnCrash.getStackTraceFromIntent(...some intent...),
// CustomActivityOnCrash.getAllErrorDetailsFromIntent(...some intent...)
);
}
#Override
public void onRestartAppFromErrorActivity() {
log(LogLevel.INFO, "COAC: app restarted");
}
#Override
public void onCloseAppFromErrorActivity() {
log(LogLevel.INFO, "COAC: app closed");
}
}
It's very slow to test datastore api in cloud in my country, I hope a way to test datastore code in local. so I found following code:
package ro.gae
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig
import com.google.appengine.tools.development.testing.LocalServiceTestHelper
/**
* Created by roroco on 8/23/15.
*/
trait LcDatastore {
LocalServiceTestHelper h = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
def iiLcDs() {
h.setUp()
}
def closeLcDs() {
h.tearDown()
}
}
But above code only save records in memory, and these records will disappear after code finish. I hope a way to save records in my disk to simplify my code
update
I hope the way don't need to start dev_server since dev_server need a long startup in java
did you try something like this?
public class MyTestClass {
LocalServiceTestHelper localServiceTestHelper;
#BeforeClass
public void beforeClass(){
LocalDatastoreServiceTestConfig localDatastoreServiceTestConfig = new LocalDatastoreServiceTestConfig();
localDatastoreServiceTestConfig.setBackingStoreLocation("storagefilelocation");
localDatastoreServiceTestConfig.setNoStorage(false);
localServiceTestHelper = new LocalServiceTestHelper(localDatastoreServiceTestConfig);
}
#Test
public void testSomething(){
}
}
edit: By the way, I aggree with #Igor Artamonov that this is very likely a bad idea. It should work though. I can also think of a few things that this could help with; like importing huge datasets into the dev local storage by running a unit test (or any external application).
I am trying to test using AndroidTestCase. I am trying to test only one particular class in my application, however this class does not extend Activity, Service or anything else. It is basically a plain Java class apart from the fact that it requires a Context. It is a pojo and some of its variables are objects that require android api calls in their creation, e.g. a call to the SensorManager.
I tried to use:
Context context = getContext();
When running my tests this gives me the exception "System services not available to activites before onCreate()". Does that method have to be overridden?
final Context context = new IsolatedContext(null, getContext()) gives the same thing.
The reason I am using the Android testing framework and not something like Robolectric is because the class I'm testing gathers hardware information about a device and so I want to run the tests on an actual device. I have looked at the developer docs for AndroidTestCase but can't see what I'm looking for in the examples. I'm not sure the other test case classes will achieve what I want. Any ideas?
My test class:
public class DeviceTest extends AndroidTestCase {
ClassToTest mClassToTest;
#Override
protected void setUp() throws Exception {
final Context context = new IsolatedContext(null, getContext()) {
#Override
public Object getSystemService(final String pName) {
return getContext().getSystemService(pName);
}
};
mClassToTest = new ClassToTest(context);
super.setUp();
}
public void testClassMethod() {
Object mObject;
mObject = mClassToTest.getObject();
assertNotNull(mObject);
}
#Override
protected void tearDown() throws Exception {
mClassToTest = null;
super.tearDown();
}
}
Thanks in advance.
UPDATE: After changing my setup to the following:
#Override
protected void setUp() throws Exception {
super.setUp();
context = this.getContext();
mClassToTest = new ClassToTest(context);
}
I am getting an error that context is null. In what scenarios would AndroidTestCase.getContext() return null? My setup seems to be ok....
From AndroidTestCase you can access directly mContext, or call getContext().
From the context returned by those, you could also call Context.getApplicationContext() if you wanted that one.
You can use mContext from super class (AndroidTestCase). I used it for the testing of the database where context is required.
AndroidTestCase.class
public class AndroidTestCase extends TestCase {
protected Context mContext;
...
}
You would be able to use Context in the inherited class of AndroidTestCase.
TestDb.java
public class TestDb extends AndroidTestCase {
void deleteTheDatabase() {mContext.deleteDatabase(DB_NAME)};
}
There are a few ways around this, you could use a mockcontext as one solution or if you really do not care what the context is just that is valid you can use an InstrumentationTestCase and get the context of the test apk via getInstrumentation().getContext().
I think the reason your context is null is that actually no android context exists at this point, you can get one by creating an application or an activity.