assertion- problems with internal call - java

hi guys Im having some problems with my frist Testing
im writing this snippet but i keep get this problem:
java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:86)
at org.junit.Assert.assertTrue(Assert.java:41)
at org.junit.Assert.assertNotNull(Assert.java:712)
at org.junit.Assert.assertNotNull(Assert.java:722)
someone know hot to help me? and maybe also which are the correct thing to test in this class? thanks a lot
I already have Junit implementation in gradle
the test class is :
public class QrActivityTest {
public QrActivity tester;
#Before
public void setUp(){
tester = new QrActivity();
}
#Test
public void onCreate() {
//barcodeDetector = new BarcodeDetector.Builder(tester.getApplicationContext()).setBarcodeFormats(Barcode.QR_CODE).build();
// Assert.assertNotNull(barcodeDetector);
Assert.assertNotNull(tester);
Assert.assertNotNull(tester.cameraSource);
}}
the class is:
public class QrActivity extends AppCompatActivity {
SurfaceView surfaceView;
CameraSource cameraSource;
TextView textView;
BarcodeDetector barcodeDetector;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.barcode_scanner_layout);
surfaceView = (SurfaceView) findViewById(R.id.camera);
textView = (TextView) findViewById(R.id.txt);
barcodeDetector = new BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.QR_CODE).build();
cameraSource = new CameraSource.Builder(this, barcodeDetector).setRequestedPreviewSize(640, 480).setAutoFocusEnabled(true).build();
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (ActivityCompat.checkSelfPermission(QrActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
try {
cameraSource.start(holder);
} catch (IOException e) {
Toast.makeText(QrActivity.this, "errore fotoamera", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
//this is to take data
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> qrCodes = detections.getDetectedItems();
if (qrCodes.size() != 0) {
textView.post(new Runnable() {
#Override
public void run() {
Vibrator vibrator = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(300);
textView.setText(qrCodes.valueAt(0).displayValue);
if (qrCodes.valueAt(0).displayValue.equals("129063")) {
Intent intent = new Intent(QrActivity.this, AttrezzaturaRecycleView.class);
startActivity(intent);
Utility.showToast(QrActivity.this, "Dispositivo trovato!");
}
}
});
}

Assertions check internal the values. If the assertion isn't met they throw an exception. So you might check the full stack trace.
The exception probably occur in the line Assert.assertNotNull(tester.cameraSource);. This is caused because cameraSource will be null. This is caused because you only create an instance of the class but no Events like onCreate are called. A simple Unit test isn't enough for front end testing.
You might need an instrumented test case. Pleas try to use the JUnit testrules to instantiate the Activity. Concider that you need a device or emulator to run this tests.

As #finder2 sais, the problem is, that tester.cameraSource is null.
I think, this is because the method onCreate() is never executed.
You may start your Application like normal or run onCreate by using Reflection.
You could also move the necessary code inside the constructor or a public method.

Related

Android Testing Activity Started by Handler.postDelayed

I'm new to using the Roboelectric testing framework and the issue that I am having is not being able to build an activity. I used the same exact test in every class and they worked as expected, except for the CallingActivity that relies on being called by Handler.postDelayed which I believe is the problem.
This is the code that will create the CallingActivity:
btnCall.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Handler().postDelayed(new Runnable()
{
#Override
public void run() {
Intent intent = new Intent(FakePhoneCallMenuActivity.this, CallingActivity.class);
intent.putExtra("callerName", nameEntryBox.getText().toString());
intent.putExtra("callerPhoneNum", phoneEntryBox.getText().toString());
intent.putExtra("callerVoice", voice);
startActivity(intent);
}
}, timeToStart);
}
});
This is test for the CallingActivity that is having issues working:
#RunWith(RobolectricTestRunner.class)
#Config(sdk = {Build.VERSION_CODES.O_MR1})
public class CallingTest {
private CallingActivity activity;
#Before
public void setUp() throws Exception {
activity = Robolectric.buildActivity(CallingActivity.class)
.create()
.start()
.resume()
.get();
}
#Test
public void acceptCallButtonClickShouldStartNewActivity() throws Exception {
ShadowActivity shadowActivity = shadowOf(activity);
ImageButton button = (ImageButton) shadowActivity.getContentView().findViewById(R.id.btnAcceptCall);
button.callOnClick();
Intent startedIntent = shadowActivity.getNextStartedActivity();
ShadowIntent shadowIntent = shadowOf(startedIntent);
assertEquals(FakePhoneCallMenuActivity.class, shadowIntent.getIntentClass());
}
}
The issue that I am recieving after trying to run this test is:
java.lang.Exception: Main looper has queued unexecuted runnables.
Help with this would be greatly appreciated!
Thanks

How initialize correctly static variable in PreferenceActivity

I have Preference class extent PreferenceActivity.
I create public static String quality; in Preference.class i add in onCreate
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref);
quality = "QUALITY_HIGH";//initialize
}
and add in Preference.class this method
public void getQuality() {
if (keyquality.equals("480p")) {
quality = "QUALITY_LOW";
//
}
if (keyquality.equals("720p")) {
//
quality = "QUALITY_720P";
}
if (keyquality.equals("1080p")) {
//
quality = "QUALITY_HIGH";
}
}
in another class i create method to get my variable and set settings
private void getqualityvideo() {
/*if (Prefernce.quality == null) {
preferencecamrecoder = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
} else {*/
if (Prefernce.quality.equals("QUALITY_LOW")) {
preferencecamrecoder = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
}
if (Prefernce.quality.equals("QUALITY_720P")) {
preferencecamrecoder = CamcorderProfile.get(CamcorderProfile.QUALITY_720P);
}
if (Prefernce.quality.equals("QUALITY_HIGH")) {
preferencecamrecoder = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
}
// }
}
Problem:
when start application
private void startServes() {
btnStart = (ImageView) findViewById(R.id.StartService);
btnStart.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
v.startAnimation(mAnimationImage);
Intent intent = new Intent(MainActivity.this, RecorderService.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent);
changeCamera
.setEnabled(false);
btnStart.setEnabled(false);
setings.setEnabled(false);
moveTaskToBack(false);
}
});
}
in another class in method
getqualityvideo() error NullPointerException
error in this first line
if (Prefernce.quality.equals("QUALITY_LOW"))
why the quality variable is empty?
The reason is that you're setting Preference.quality in the onCreate method in your Preference class. So what's probably happening is that when you start your application in your other class, Preference.quality is going to be null because it was never initialized to anything. The reason is that the other class has no way to access the onCreate method in your Preference class as of now. onCreate is executed when an activity starts, but that doesn't seem to happen anywhere in your code. A solution could be to initialize public static String quality outside of your onCreate method but still within the Preference class,
public static String quality = "QUALITY_HIGH";
#Override
public void onCreate(Bundle savedInstanceState) {
//insert code here
}
The problem was merely a scope issue.

ViewRootImpl.setPausedForTransition(boolean) NullPointerException in ActivityTransitionCoordinator when transition to other Activity invoked too early

In my Android app, I have a splash screen where I do some setup and loading. My app uses default explode as a windowEnterTransition and a windowExitTransition and a changeImageTransform plus changeBounds transition set as a windowSharedElementEnterTransition and windowSharedElementExitTransition. For convenience, I start the next Activity using a static method where I pass the current Activity as a Context and a shared element. The code is provided in the second part of this post.
One of the scenarios is that there is nothing to load, so app almost immediately fires the next Activity. The problem is that in this case app somehow enigmatically crashes in an ActivityTransitionCoordinator with a stack given in the next part of this post. Debugging of the internals shows that ViewRootImpl that is achieved there is null and there is no null check, so invoking viewRoot.setPausedForTransition(false) throws a NullPointerException. You can find this unlucky spot marked in the code below.
To focus on this failing scenario, let’s make an assumption that a logic deciding that there is nothing to load and the next Activity should be started immediately is so simple, that it could be simplified to just starting the mentioned activity.
It makes no difference if a start of the second Activity is invoked in onCreate(), onResume(), or onEnterAnimationComplete() method. I even tried adding a listener on a Transition acquired by calling getWindow().getSharedElementEnterTransition() and getWindow().getEnterTransition() to be allowed to start the next Activity when transitions are finished. The given Transitions are not null, but app never goes into methods of attached listeners.
The workaround I use now is just to schedule a Runnable to make an invoking of the next Activity delayed.
I’m wondering if this is an Android (a SupportLibrary to be more specific) issue, or I missed something. Has anyone encountered a similar problem?
A stacktrace:
08-12 00:35:32.550 26453-26453/com.faver.mkoslacz.faverdemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.faver.mkoslacz.faverdemo, PID: 26453
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.ViewRootImpl.setPausedForTransition(boolean)' on a null object reference
at android.app.ActivityTransitionCoordinator.startInputWhenTransitionsComplete(ActivityTransitionCoordinator.java:897)
at android.app.ActivityTransitionCoordinator.viewsTransitionComplete(ActivityTransitionCoordinator.java:885)
at android.app.ExitTransitionCoordinator.getExitTransition(ExitTransitionCoordinator.java:318)
at android.app.ExitTransitionCoordinator.beginTransitions(ExitTransitionCoordinator.java:365)
at android.app.ExitTransitionCoordinator.-wrap0(ExitTransitionCoordinator.java)
at android.app.ExitTransitionCoordinator$4.run(ExitTransitionCoordinator.java:216)
at android.app.ActivityTransitionCoordinator.startTransition(ActivityTransitionCoordinator.java:773)
at android.app.ExitTransitionCoordinator.startExit(ExitTransitionCoordinator.java:213)
at android.app.ActivityTransitionState.startExitOutTransition(ActivityTransitionState.java:317)
at android.app.Activity.cancelInputsAndStartExitTransition(Activity.java:3960)
at android.app.Activity.startActivityForResult(Activity.java:3936)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:48)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:75)
at android.app.Activity.startActivity(Activity.java:4196)
at com.faver.mkoslacz.faverdemo.activity.AuthorizationActivity.startWithTransiton(AuthorizationActivity.java:45)
at com.faver.mkoslacz.faverdemo.activity.SplashActivity.onEnterAnimationComplete(SplashActivity.java:27)
at android.app.Activity.dispatchEnterAnimationComplete(Activity.java:5852)
at android.app.ActivityThread.handleEnterAnimationComplete(ActivityThread.java:2668)
at android.app.ActivityThread.-wrap10(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1558)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
A code failing in ActivityTransitionAnimator:
private void startInputWhenTransitionsComplete() {
if (mViewsTransitionComplete && mSharedElementTransitionComplete) {
final View decor = getDecor();
if (decor != null) {
final ViewRootImpl viewRoot = decor.getViewRootImpl(); // it's null
viewRoot.setPausedForTransition(false); // crashes here
}
onTransitionsComplete();
}
}
A method starting the next Activity:
public static void startWithTransiton(Activity activity, android.view.View logo) {
Intent intent = new Intent(activity, AuthorizationActivity.class);
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation(
activity,
logo,
activity.getString(R.string.logoTransfer));
activity.startActivity(intent, options.toBundle());
}
The splash Activity contents (simplified):
public class SplashActivity extends AppCompatActivity {
private static final String TAG = "SplashActivity";
private View logo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
logo = findViewById(R.id.logo);
// AuthorizationActivity.startWithTransiton(this, logo); // will fail
new Handler().postDelayed(() -> {
AuthorizationActivity.startWithTransiton(this, logo); // executes flawlessly
}, 300);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
Transition sharedElementEnterTransition = getWindow().getSharedElementEnterTransition();
if (sharedElementEnterTransition != null) {
sharedElementEnterTransition.addListener(new Transition.TransitionListener() {
#Override
public void onTransitionStart(Transition transition) {
Log.d(TAG, "onTransitionStart: never executes");
}
#Override
public void onTransitionEnd(Transition transition) {
Log.d(TAG, "onTransitionEnd: never executes");
}
#Override
public void onTransitionCancel(Transition transition) {
Log.d(TAG, "onTransitionCancel: never executes");
}
#Override
public void onTransitionPause(Transition transition) {
Log.d(TAG, "onTransitionPause: never executes");
}
#Override
public void onTransitionResume(Transition transition) {
Log.d(TAG, "onTransitionResume: never executes");
}
});
}
Transition enterTransition = getWindow().getEnterTransition();
if (enterTransition != null) {
enterTransition.addListener(new Transition.TransitionListener() {
#Override
public void onTransitionStart(Transition transition) {
Log.d(TAG, "onTransitionStart: never executes");
}
#Override
public void onTransitionEnd(Transition transition) {
Log.d(TAG, "onTransitionEnd: never executes");
}
#Override
public void onTransitionCancel(Transition transition) {
Log.d(TAG, "onTransitionCancel: never executes");
}
#Override
public void onTransitionPause(Transition transition) {
Log.d(TAG, "onTransitionPause: never executes");
}
#Override
public void onTransitionResume(Transition transition) {
Log.d(TAG, "onTransitionResume: never executes");
}
});
}
}
}
#Override
protected void onResume() {
super.onResume();
// AuthorizationActivity.startWithTransiton(this, logo); // will fail
}
#Override
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
// AuthorizationActivity.startWithTransiton(this, logo); // will fail
}
}
I'm also facing same issue while working with Explode Activity transition,I find one thing this code running normally in Lollipop version, But crashed above Lollipop.
Even i can't find out the reason for crashing. But i resolve it another way. Just put delay in activity transition. I given my code below
public class SplashActivity extends AppCompatActivity {
final Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
handler.postDelayed(new Runnable() {
#Override
public void run() {
navigate();
}
},500);
}
private void navigate() {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this);
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent, options.toBundle());
}}
After adding this working normally in all version.
Instead of using a Handler you can navigate to the next activity using your root view post method
findViewById(<Your activity root view id>).post(() -> navigate());
In general, the root view could be android.R.id.content

Mock a method to get code coverage in Android

I am writing an Android OpenGL ES 2.0 application in a test driven fashion. Here goes my code.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
boolean checkCompatability = checkForDeviceCompatablity();
if(checkCompatability)
{
Toast.makeText(this, "Your device is opengl compatible", Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(this, "Your device does not support OpenGL", Toast.LENGTH_LONG).show();
}
}
public boolean checkForDeviceCompatablity() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = manager.getDeviceConfigurationInfo();
boolean result = info.reqGlEsVersion >= 0x20000
|| (Build.VERSION.SDK_INT
>= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1);
return result;
}
}
And this is my test
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
private MainActivity mActivity;
public MainActivityTest(Class<MainActivity> activityClass) {
super(activityClass);
}
public MainActivityTest(){
super(MainActivity.class);
}
//The below method would always return me a true as I test it in a real device.
public void testIntegrationCheckForConfiguration() {
mActivity = getActivity();
mActivity.startActivity(mActivity.getIntent());
boolean resultConfiguration = mActivity.checkForDeviceCompatablity();
assertNotNull(resultConfiguration);
}
//I need to mock the above method into something like the below method so that I can get coverage for the else block.
public void testCheckForConfigurationWhenDeviceIsOfInCorrectConfiguration(){
mActivity = new MainActivity(){
#Override
public boolean checkForDeviceCompatablity() {
return false;
}
};
mActivity.startActivity(mActivity.getIntent());
boolean compatability = mActivity.checkForDeviceCompatablity();
assertTrue(compatability);
}
}
I know I'm doing it incorrectly. But I need a way to mock the checkForDeviceCompatability to make it return false. When I run the test I get a NullPointerException at the startActivity call. How do I mock the function checkForDeviceCompatability and get the code cover the else part in MainActivity class?
Also is this possible with any kind of mocking framework?
Not that I have much experience with this sort of thing but you could try Mockito.
Noticed it in the examples when integrating Dagger dependency injection to my app.

Java, using an interface as a callback

I have been developing a simple touch handler for Android with the possibilites of firing callbacks like onUpdate (when the screen is touched) without having to setup threads. My problem is that my knowledge of Java is fairly limited and i can't do it because i know very little of how to use interfaces. I'm pretty sure that my problem may be a simple typo or something, but i get a NullPointerException when i execute the method from the touch handler (which processed the touch information) so that i can do what i need in the main activity class.
This is the main class code (cut from the irrelevant stuff):
//package and imports
public class Test extends Activity implements TouchHelper {
StringBuilder builder = new StringBuilder();
TextView textView;
TouchReader touchReader;
List<TouchTable> touchTablesArray;
TouchTable touchTable;
public static final String Tag = "TouchTest";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
textView = new TextView(this);
Log.d(Tag, "TextView initialized " + textView);
textView.setText("Touch and drag (multiple fingers supported)!");
touchReader = new TouchReader(textView);
Log.d(Tag, "touchReader initialized");
touchTablesArray = touchReader.getTouchTables();
setContentView(textView);
}
#Override
public void onTouchUpdate(int pointerId)
{
Log.d(Tag, "onTouchUpdate called");
touchTable = touchTablesArray.get(pointerId);
Log.d(Tag, "touchTable get successful");
//writing on stringbuilder
}
}
This is the code of the handler itself:
//package and imports
public class TouchReader implements OnTouchListener
{
public final static String Tag = "TouchReader";
List<TouchTable> touchTables;
TouchHelper helper;
TouchTable touchTable = new TouchTable();
public TouchReader(View view)
{
view.setOnTouchListener(this);
touchTables = new ArrayList<TouchTable>(10);
Log.d(Tag, "TouchReader initialized");
}
public boolean onTouch(View v, MotionEvent event)
{
synchronized(this)
{
//all the common code handling the actual handling, with switches and such
touchTables.add(pointerId, touchTable); //obviously the pointerId is defined earlier
Log.d(Tag, "Values updated");
helper.onTouchUpdate(pointerId); //the exception is here
Log.d(Tag, "Update called");
}
return true;
}
public List<TouchTable> getTouchTables()
{
synchronized(this)
{
return touchTables;
}
}
}
As you can see the error is most likely due to my inability to correctly use an interface, and yet all the official docs confused me even more.
Finally, the tiny code of the interface:
//package
public interface TouchHelper
{
public void onTouchUpdate(int pointerId);
}
I hope this question isn't too noobish to post it here :)
EDIT: Thanks to all for the help, in the end i followed Bughi's solution.
Your TouchHelper helper; is null, it needs a instance of the interface to be able to call methods on it -in your case the main activity class that implements your interface-
Make a set method for the listener
public void setOnTouchListener(TouchHelper helper)
{
this.helper = helper;
}
Then call it from on create:
public class Test extends Activity implements TouchHelper {
...
#Override
public void onCreate(Bundle savedInstanceState)
{
...
touchReader = new TouchReader(textView);
touchReader.setOnTouchListener(this);
...
}
}
Also add a null check to your on touch method:
public boolean onTouch(View v, MotionEvent event)
{
synchronized(this)
{
//all the common code handling the actual handling, with switches and such
touchTables.add(pointerId, touchTable); //obviously the pointerId is defined earlier
Log.d(Tag, "Values updated");
if (helper != null)
helper.onTouchUpdate(pointerId); //the exception is here
Log.d(Tag, "Update called");
}
return true;
}
If the NullPointerException is here:
helper.onTouchUpdate(pointerId);
Then simply helper is null, where do you initialize it?
I see that you define it:
TouchHelper helper;
But do you ever have?
helper = ...
I know this is old, but I was stuck on this myself. Sam's post above helped me think of it.
I finally added an onAttach method that that checks that the interface is initialized as well as implemented to the main activity that it interfaces with. I added a Log.i inside the main activity to test.
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mainActivityCallback = (OnSomethingSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnSomethingSelectedListener");
}
}
In TouchReader you define a TouchHelper but nowhere in the code an object is created or an existing object is assigned to that attribute. So it is still null when you try to use it.
helper is null in your in TouchReader
To fix this make the TouchReader take a TouchHelper:
public TouchReader(View view, TouchHelper helper) {
...
this.helper = helper;
...
}
Then in your activity:
touchReader = new TouchReader(textView, this);
Try initializing it in your constructor; all reference that aren't initialized are set to null.
// I see no reason why this should be a member variable; make it local
StringBuilder builder = new StringBuilder();
TextView textView;
TouchReader touchReader;
List<TouchTable> touchTablesArray;
TouchTable touchTable;
public TouchReader(View view)
{
// textView is null
// touchReader is null
view.setOnTouchListener(this);
// why "10"? why a List of touchTables and a touchTable member variable? why both?
touchTables = new ArrayList<TouchTable>(10);
Log.d(Tag, "TouchReader initialized");
// touchTable is null;
}

Categories

Resources