我正在尝试学习Mockito和TDD。
我有方法的演示者:
@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;
}
问题是如何使用Mockito Roboelectric或w / e在底部测试2种方法。
@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();
}
我添加了PowerMock并创建了测试以确保它能正常工作^^我正在添加测试,显示我想要做什么但不知道怎么做
我的想法是将此接口方法作为presenter中的受保护方法并创建MockingClass。或者创建单独的界面助手并模拟它。
我对任何干净的解决方案/主张持开放态度。
答案 0 :(得分:1)
每当我看到有人开始使用Powermockito进行新项目时,我会立即想起Padme在第3集中对Anakin所说的话:
你走的是我无法追踪的道路
这里不需要Powermockito - 只是老Java和Mockito: - )
您的Presenter中有一些公共方法,应该将它们提取到单独的类中。最好的演示者只需将他们的动作委托给其他类,并使用show方法操作视图。这是演示者的唯一责任。你可以轻松地做这样的事情:
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;
}
}
然后:
class BluetoothAdapterWrapper {
private final BluetoothAdapter bluetoothAdapter;
BluetoothAdapterWrapper(BluetoothAdapater adapter) {
this.bluetoothAdapter = adatper;
}
public boolean isBluetoothEnabled() {
return bluetoothAdapter.isEnabled();
}
}
现在您的演示者看起来像这样:
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();
}
}
您现在注意到我们甚至不需要在演示者上使用这些公共方法 - 您可以将它们从演示者的合同中删除,如果您愿意,可以将它们设为私有或完全删除它们。
现在您的测试看起来像这样:
@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();
}