How to mock user interaction (“fromUser=true”) wit

2019-05-26 14:40发布

问题:

My code distinguishes user and code interactions with the SeekBar using fromUser parameter passed to onProgressChanged() method:

        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean fromUser) {

            if (fromUser) {
                // execute only if it was user interaction with the SeekBar
                ...
            }
        }

When I'm trying to test my SeekBar with robotium I'm not able to "mock user interaction with the SeekBar":

 solo.setProgressBar(mSeekBar, newValue);

onProgressChanged() callback is executed with fromUser == false.

Is it possible to write Robotium test that sets SeekBar's progress and mocks user interaction (fromUser == true) at the same time?

Thanks!

回答1:

You cannot achieve that with method setProgressBar, because it uses setProgress from ProgressBar.setProgress so there is fromUser set to false by default.

  1. solution is to use click on screen - but you actually don't know exactly in which point (% of progress) you hit, if you hit on progress bar at all.

  2. solution is to use reflection - use setProgress method with extra parameter (fromUser), so it will use the protected method. I can help in implementation of that in case you have problems with it.

  3. solution is to ask robotium team to implement method from 2nd point.



回答2:

Solution (Reflections)

SeekBar is an indirect subclass of the ProgressBar that has a public setProgress(int) that has only one line that calls package method setProgress(int, boolean) and passes fromUser == false to it. It is possible to use Reflections and to call setProgress(int, boolean) directly and pass desired fromUser parameter:

    private void setSeekBarProgress(int newProgress, boolean fromUser) {

        Method privateSetProgressMethod = null;

        try {
            privateSetProgressMethod = ProgressBar.class.getDeclaredMethod("setProgress", Integer.TYPE, Boolean.TYPE);
            privateSetProgressMethod.setAccessible(true);
            privateSetProgressMethod.invoke(mSeekBar, newProgress, fromUser);
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
            fail("Error while invoking private method.");
        }
    }