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!
You cannot achieve that with method setProgressBar, because it uses setProgress from ProgressBar.setProgress so there is fromUser set to false by default.
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.
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.
solution is to ask robotium team to implement method from 2nd point.
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.");
}
}