Reputation: 1586
I'm trying to learn Mockito and TDD.
I have presenter with methods:
@Override
public void startScanning() {
if (isLocationPermissionGranted() && isBluetoothEnabled()) {
mPresenterView.onStartScanBtnClick();
} else if (!isBluetoothEnabled()) {
mPresenterView.displayDialogRequestingBluetooth();
} else if (!isLocationPermissionGranted()) {
mPresenterView.displayDialogRequestingPermission();
}
}
@Override
public boolean isLocationPermissionGranted() {
return false;
}
@Override
public boolean isBluetoothEnabled() {
return false;
}
Question is how I can test 2 methods on the bottom using Mockito Roboelectric or w/e.
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mScanningPresenter = new ScanningPresenter(mView);
mockBluetoothAdapter = PowerMockito.mock(BluetoothAdapter.class);
}
@Test
public void shouldPassPowerMock() {
assertEquals(true, mockBluetoothAdapter != null);
}
@Test
public void shouldDisplayBluetoothRequestWhenDisabled() {
mScanningPresenter.startScanning();
PowerMockito.when(!mockBluetoothAdapter.isEnabled()).thenReturn(false);
verify(mView).displayDialogRequestingBluetooth();
}
I added PowerMock and created test to be sure it's working ^^ and I'm adding test which showing what I want TO DO but don't know how yet
My idea is to make this interface methods as protected method in presenter and create MockingClass. Or Create seperate interface helper and mock it.
I have open mind for any clean solutions / propositions.
Upvotes: 1
Views: 1053
Reputation: 21437
Whenever I see someone start to use Powermockito for a new project I immediately think of Padme's words to Anakin in Episode 3:
You're going down a path I can't follow
There's no need for Powermockito here - just good old Java and Mockito :-)
You have some public methods in your Presenter which should probably be extracted to separate classes. The best kinds of presenters simply delegate their actions to other classes and manipulate the view using show methods. That is the single responsibility of the presenter. You could easily do something like this:
class PermissionsChecker {
private final Context context;
PermissionsChecker(Context context) {
this.context = context;
}
public boolean isLocationPermissionGranted() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
return false;
if (context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED)
return false;
return true;
}
}
Then:
class BluetoothAdapterWrapper {
private final BluetoothAdapter bluetoothAdapter;
BluetoothAdapterWrapper(BluetoothAdapater adapter) {
this.bluetoothAdapter = adatper;
}
public boolean isBluetoothEnabled() {
return bluetoothAdapter.isEnabled();
}
}
Now your presenter looks something like this:
class ScanningPresenter {
private final ScanningView scanningView;
private final PermissionsChecker permissionsChecker;
private final BluetoothAdapterWrapper bluetoothAdapterWrapper;
ScanningPresenter(ScanningView scanningView, PermissionsChecker permissionsChecker, BluetoothAdapterWrapper bluetoothAdapterWrapper) {
this.scanningView = scanningView;
this.permissionsChecker = permissionsChecker;
this.bluetoothAdapterWrapper = bluetoothAdapterWrapper;
}
@Override
public void startScanning() {
if (isLocationPermissionGranted() && isBluetoothEnabled()) {
scanningView.onStartScanBtnClick();
} else if (!isBluetoothEnabled()) {
scanningView.displayDialogRequestingBluetooth();
} else if (!isLocationPermissionGranted()) {
scanningView.displayDialogRequestingPermission();
}
}
@Override
public boolean isLocationPermissionGranted() {
return permissionsChecker.isLocationPermissionGranted();
}
@Override
public boolean isBluetoothEnabled() {
return bluetoothAdapterWrapper.isEnabled();
}
}
You notice now we don't even need those public methods on the presenter - you can remove them from the presenter's contract and make them private or completely get rid of them if you want.
Now your test looks something like this:
@Mock PermissionsChecker mockPermissionsChecker;
@Mock BluetoothAdapterWrapper mockBluetoothAdapterWrapper;
@Mock ScanningView mockScanningView;
//system under test
ScanningPresenter scanningPresenter;
@Before
public void setUp() {
MockitoAnnotations.init(this);
scanningPresenter = new ScanningPresenter(mockScanningView, mockPermissionsChecker, mockBluetoothAdapterWrapper);
}
@Test
public void shouldDisplayBluetoothRequestWhenDisabled() {
//arrange
when(mockBluetoothAdapter.isEnabled()).thenReturn(false);
//act
mScanningPresenter.startScanning();
//assert
verify(mockScanningView).displayDialogRequestingBluetooth();
}
Upvotes: 3