I am new to Robolectric testing in Android Studio and when I try to run tests, the same error appears which states android.content.res.Resources$NotFoundException: Unable to find resource ID #0x0 in packages. I made sure that the JUnit Working Directory was $MODULE_DIR$, but it still didn't work. Adding testOptions.unitTests.includeAndroidResources to my build.gradle file doesn't do anything either. Here is what the test file looks like:
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
public class StartActivityTests {
StartActivity activity;
#Before
public void setUp() throws Exception {
activity = Robolectric.buildActivity(StartActivity.class)
.create()
.resume()
.get();
}
#Test
public void shouldNotBeNull() throws Exception
{
assertNotNull(activity);
}
#Test
public void clickingNewGame_shouldStartAvatarRoomActivity() {
StartActivity activity = Robolectric.setupActivity(StartActivity.class);
activity.findViewById(R.id.newUserButtonFirstPage).performClick();
Intent expectedIntent = new Intent(activity, AvatarRoomActivity.class);
Intent actual = ShadowApplication.getInstance().getNextStartedActivity();
assertEquals(expectedIntent.getComponent(), actual.getComponent());
}
}
Please help! It would be greatly appreciated!
If you are using Android Gradle Plugin 3.0 or above, you need to add the following snippet with the android block of build.gradle
testOptions {
unitTests {
includeAndroidResources = true
}
}
or no Android resource can be found in unit tests.
I changed my SDK to 27 in the build.gradle file and the Robolectric tests succeeded.
Related
I am trying to make the native side of my android app to communicate with Flutter.
This is on the Flutter side:
static const platform = const MethodChannel('getHallInfo');
#override
void initState() {
testing().then((String lst) {
setState(() {
if (lst != null) str = lst;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[Text(str)],
);
}
static Future<String> testing() async {
String lst;
try {
lst = await platform.invokeMethod('getHalls');
} catch (e) {
print(e.toString());
}
return lst;
}
And this is on the native Java:
private static final String CHANNEL = "getHallInfo";
super.configureFlutterEngine(getFlutterEngine());
GeneratedPluginRegistrant.registerWith(getFlutterEngine());
new MethodChannel(getFlutterEngine().getDartExecutor().getBinaryMessenger(), CHANNEL).setMethodCallHandler(new MethodChannel.MethodCallHandler() {
#Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
if (methodCall.method.equals("getHalls")) {
String mm= "Succeeded";
System.out.println("Entered");
result.success(mm);
}
}
});
My Pubspec.yaml:
name: flutterModule
description: A new flutter module project.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.3
flutter_svg: ^0.17.4
google_fonts: ^1.1.0
intl: ^0.16.1
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
assets:
- assets/icons/
module:
androidX: true
androidPackage: com.example.flutterModule
iosBundleIdentifier: com.example.flutterModule
This is the error I get:
MissingPluginException(No implementation found for method getHalls on channel getHallInfo)
Note: "Entered" is shown on the terminal
Edit: These are the things that I tried:
Run flutter clean
Run flutter upgrade
Restart the app
But this exception persists.
Try flutter clean
then flutter upgrade
then flutter run -v
If that doesn't work, have a look at the following issues:
issue01,
issue02
I hope this will help you
you just have to stop the app and restart it again.
make sure you did pub get before you stop your app.
use the command .
flutter pub get
you just need to run
Flutter clean
then again restart/run your app
I am setting up an automated framework to run tests on Android emulators, using Appium. I have added logic to launch Appium and the emulator programatically, but would like to be able to edit the "launch settings" from the TestRunner class.
My ideal goal is to have everything I need in the TestRunner class, so I can run my tests against a specific port, emulator, and tags.
But currently with the method I have now, I am receiving the following error:
'Message: cucumber.runtime.CucumberException: Hooks must declare 0 or 1 arguments.'
#CucumberOptions(
plugin = {"pretty", "html:target/cucumber-reports"}
, monochrome = true
, features = "src/test/java/feature"
, tags = "#Login"
)
public class TestRunner {
public void run() throws MalformedURLException, InterruptedException {
setUpDriver(4723, "Android9");
}
}
_________________________________________________________
public class Hooks extends DriverFactory {
static AppiumDriverLocalService service;
#Before
public static void setUpDriver(int port, String simulator) throws InterruptedException {
service = AppiumDriverLocalService
.buildService(new AppiumServiceBuilder().usingPort(port)
.usingDriverExecutable(new File("path/to/node/file"))
.withAppiumJS(new File("/path/to/appium/file")));
System.out.println("\n Appium server: " + service.getUrl());
service.start();
Thread.sleep(2000);
try {
setUpMobileDriver(simulator);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
You can pass from Maven or you can use System properties
I'm trying to use a fragment autocomplete UI from ---> https://docs.mapbox.com/android/plugins/overview/places/
but the IDE says that it can't resolve the symbol CarmenFeature and I don't know how to import that class or solve this exception
I've tried :
to import ---> import com.mapbox.api.v4.models.CarmenFeature;
but I think that the API folder does not exist
sync with gradle
invalidate cache and restart
rebuild project
clean project
autocompleteFragment = (SupportPlaceAutocompleteFragment) getSupportFragmentManager().findFragmentByTag(TAG);
autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected( CarmenFeature carmenFeature) {
}
#Override
public void onError(Status status) {
}
});
Well the problem is that the class cannot be imported and loaded. You need to configure inside the build.gradle in the root of your project :
allprojects {
repositories {
...
...
maven
{
url 'https://mapbox.bintray.com/mapbox'
}
}
}
and inside your /app/build.gradle :
dependencies {
...
...
// MAPBOX DEPENDENCIES
implementation ('com.mapbox.mapboxsdk:mapbox-android-sdk:6.5.0#aar')
{
transitive=true
}
implementation 'com.mapbox.mapboxsdk:mapbox-android-navigation:0.20.0'
implementation ('com.mapbox.mapboxsdk:mapbox-android-navigation-ui:0.20.0')
{
transitive = true
}
implementation 'com.google.android.gms:play-services-maps:16.0.0'
implementation 'com.android.support:design:27.0.2'
}
this is enough to use the CarmenFeature class.
I am trying to add a native prebuilt shared library to my project in Android Studio. I am using the gradle-experimental:0.6.0-alpha5. However, whenever I try to add the prebuilt shared library to my application model, I get the following error:
Error:Cause:
org.gradle.api.internal.PolymorphicDomainObjectContainerConfigureDelegate
The library is added into the application model how it is described by the Google Gradle Experimental Guide:
repositories {
prebuilt(PrebuiltLibraries) {
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("/path_to_libs/${targetPlatform.getName()}/shared_lib.so")
}
}
}
android.sources {
main {
jniLibs {
dependencies {
library "shared_lib"
}
}
}
}
The crucial line is library "shared_lib". There is no error if I uncomment this line.
Since this is not working, I have also tried to use the guide from ph0b.com. They are using a different syntax for adding native shared libraries (I just left out the headers since I do not have a single directory including all headers):
repositories {
libs(PrebuiltLibraries) {
shared_lib {
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("/path_to_libs/${targetPlatform.getName()}/shared_lib.so")
}
}
}
}
android.sources {
main {
jni {
dependencies {
library "shared_lib" linkage "shared"
}
}
}
}
Nevertheless, this does not work as well. Android Studio does not copy my shared_lib to the apk file. Hence, I always get the following error:
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader [...] couldn't find "shared_lib.so"
Can anyone tell me how I can include native prebuild library into my project? I am using buildToolsVersion = '22.0.1' and compileSdkVersion = 22 as build parameters.
This one worked for me (0.6.0-beta6).
repositories {
prebuilt(PrebuiltLibraries) {
YourLib {
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("src/main/libs/armeabi-v7a/libYourLib.so")
}
}
}
}
android.sources {
main {
jniLibs {
dependencies {
library "YourLib"
}
}
}
}
Looks like they just forgot to mention the "YourLib {}" part around "binaries.withType".
I want to add robolectric to an existing and live android-dagger project
The problem is that the package name in the AndroidManifest is not aligned with the R file physical path.
robolectric searches for the R file according to the manifest "package_name" attribute.
I thought to use #Config over my robolectric test
#Config(manifest = " --my---path/AndroidManifest.xml",
sdk = 21,
packageName = "com.google.andorid.apps.ridematch",
application = TestApplication.class)
but apparently the "packageName" annotation is not effective.
I wanted to debug this in the robolectric open source,
but wasn't sure where was the problematic code.
It was a chance for me to first contribute to a github open-source project
my tries:
try 1)
I thought the bug is in code:
#Test
public void shouldAssignThePackageNameFromTheManifest() throws Exception {
AndroidManifest appManifest = newConfigWith("com.wacka.wa", "");
Application application = defaultTestLifecycle.createApplication(null, appManifest, null);
shadowOf(application).bind(appManifest, null);
assertThat(application.getPackageName()).isEqualTo("com.wacka.wa");
assertThat(application).isExactlyInstanceOf(Application.class);
}
so I wrote this code:
#Test
public void shouldAssignThePackageNameFromConfigWhenHaveConfigAndManifest() throws Exception {
AndroidManifest appManifest = newConfigWith("com.wacka.wa", "");
Properties properties = new Properties();
properties.put("packageName", "com.robolectric.MyTestClass");
properties.put("application", "com.robolectric.TestTestApplication");
// properties.put("application", "FakeApp");
Config config = Config.Implementation.fromProperties(properties);
Application application = defaultTestLifecycle.createApplication(null, appManifest, config);
shadowOf(application).bind(appManifest, null);
assertThat(application.getPackageName()).isEqualTo("com.robolectric.MyTestClass");
assertThat(application).isExactlyInstanceOf(TestTestApplication.class);
}
In "bind" i made non null config-package name override appManifest package name.
but I couldn't find who calls "defaultTestLifecycle.createApplication"
try 2)
I started looking at this class and its tests:
#Override
protected AndroidManifest getAppManifest(Config config) {
I saw this test:
#Ignore
#Config(constants = BuildConfig.class, packageName = "fake.package.name")
public static class PackageNameTest {
#Test
public void withoutAnnotation() throws Exception {
}
}
and I have added mine:
#Ignore
#Config(constants = BuildConfig.class, packageName = "fake.package2.name", manifest = "//java/com/google/android/apps/ridematch/environments/debug:AndroidManifest.xml")
public static class PackageNameConfigAndManifestTest {
#Test
public void withoutAnnotation() throws Exception {
}
}
but the test passed, so the bug is not there.