I know cordova-plugin-test-framework will help in testing any cordova project.
I am developing a custom camera cordova plugin for Android platform. I would like to write some Junit/Instrumentation test cases for my custom camera Android plugin code.
I am facing issues as I can't create CordovaInterface
, CordovaWebView
Objects from my test class.
Is there anyway that I can create CordovaInterface
, CordovaWebView
Objects from my test class and pass these as parameters for my custom camera Android plugin excute
method.
I would like to avoid unit test cases at js level using cordova-plugin-test-framework and write some Junit test cases (as I will have access to most of the internal classes my camera cordova plugin use). please correct me, if this wrong approach.
First, Copy CordovaLib to your plugin project as library.
Add something like this to your Test class:
first, an activity, don't forget to add it to AndroidMainfest.xml for testing.
public class TestActivity extends CordovaActivity {
CordovaWebView getWebView(){
return this.appView;
}
CordovaInterface getInterface(){
return this.cordovaInterface;
}
public void init(){
super.init();
}
}
In your test class:
@Rule
public ActivityTestRule<CordovaActivity> mActivityRule =
new ActivityTestRule<CordovaActivity>(CordovaActivity.class);
private CordovaWebView wv;
private CordovaInterface cordovaInterface;
private YourCordovaPlugin km;
private TestActivity activity;
@Before
public void Init() throws InterruptedException {
km = new KM1930CordovaPlugin();
activity = mActivityRule.getActivity();
Runnable action = new Runnable() {
@Override
public void run() {
activity.init();
wv = mActivityRule.getActivity().getWebView();
cordovaInterface = mActivityRule.getActivity().getInterface();
km = new YourCordovaPlugin();
km.initialize(cordovaInterface,wv);
wv.getPluginManager().addService(new PluginEntry("YourServiceName",km));
synchronized (this) {
this.notify();
}
}
};
synchronized( action ) {
activity.runOnUiThread(action);
action.wait() ;
}
}
Then you can add your test method and call method by invoking execute
method.
@Test
public void TestBluetooth() throws JSONException {
this.km.execute("echo","[]",new CallbackContext("0",wv));
}
In my case I had to modify a little this approach:
First of all, my TestActivity
had to be at the same level as the activity using the <action android:name="android.intent.action.MAIN" />
intent-filter
.
Then, create the test file (in my case MyTestActivityTest.java
IN THE src/androidTest/java/com/your/package/name (super important that this is an Instrumentation Test!!)
Then, on the test itself:
import android.support.test.rule.ActivityTestRule;
import android.support.test.rule.UiThreadTestRule;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Rule;
import org.junit.runner.RunWith;
import java.util.concurrent.CountDownLatch;
@RunWith(AndroidJUnit4.class)
public class MyTestActivityTest {
@Rule
public ActivityTestRule<TestActivity> mActivityRule = new ActivityTestRule<>(TestActivity.class);
@Rule
public UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();
private YourPlugin mockYourPlugin;
private CordovaWebView cordovaWebView;
private CordovaInterface cordovaInterface;
private TestActivity activity;
@Before
public void setUp() throws Throwable {
activity = mActivityRule.getActivity();
assertNotNull(activity);
final CountDownLatch signal = new CountDownLatch(1); --> this one is the important! the sync part got stucked!
Runnable action = () -> {
activity.init();
cordovaWebView = mActivityRule.getActivity().getWebView();
cordovaInterface = mActivityRule.getActivity().getInterface();
mockYourPlugin = new YourPlugin();
mockYourPlugin.initialize(cordovaInterface, cordovaWebView);
cordovaWebView.getPluginManager().addService(new PluginEntry("YourServiceName", mockBankId));
signal.countDown();// notify the count down latch, i.e release it
};
uiThreadTestRule.runOnUiThread(action);
signal.await();// wait for callback
}
@Test
public void TestBluetooth() throws JSONException {
this.mockYourPlugin.execute("echo","[]",new CallbackContext("0", cordovaWebView));
}
}
and my build.gradle
file I have this dependencies:
// JUnit 4 framework
implementation 'junit:junit:4.12'
// required if you want to use Mockito for unit tests
implementation 'org.mockito:mockito-core:2.13.0'
implementation 'org.mockito:mockito-android:2.8.47'
implementation 'com.android.support.test:rules:1.0.2'
and don't forget to put this also in the build.gradle
file:
defaultConfig {
...
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
...
}
I really hope this helps