j2e*_*nue 6 data-binding wpf android mvvm
我一直在网上搜索,但我无法找到如何使用 MVVM 更好地进行测试。我有一个与视图接口的 viewModel 的想法,但我不知道如何使用 MVVM 编写好的测试用例。我已经在 Android 中有以下 ViewModel:
public class ViewModel extends BaseObservable {
private long countDownTime;
private MyCountDownTimer mCountDownTimer;
private final String TAG = getClass().getSimpleName();
@Bindable
public long getCountDownTime() {
return countDownTime;
}
public void setCountDownTime(long countDownTime) {
this.countDownTime = countDownTime;
notifyPropertyChanged((int) BR.countDownTime);
Log.d(TAG,"prime tick:"+countDownTime);
}
public void startCounting(Long milli){
mCountDownTimer.restartTimer(milli);
}
}
Run Code Online (Sandbox Code Playgroud)
然后我有一个使用它的 xml 视图。我还有一个活动,它实际上将 xml 绑定到这个视图。此活动如下所示:
public class MainActivity extends FragmentActivity {
CountdownBinder mCountdownBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
mCountdownBinder = DataBindingUtil.setContentView(this, R.layout.activity_main);
//Lets reference our textview just for fun
mCountdownBinder.tvGreen.setText("initial text");
ViewModel viewModel = ViewModel.instance();
//now tell databinding about your viewModel below
mCountdownBinder.setViewModel(viewModel);
viewModel.startCounting(200000L);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我很困惑如何使测试更好。我读过它,但我需要一个真实世界的例子。如果重要的话,此代码来自此处的博客。
显然我可以更轻松地测试我的单元测试,对吗?我只会在 MVVM 中测试 viewModel 吗?主要需要测试什么?
您的假设是正确的,即您只对 ViewModel 和模型进行单元测试。UI 本身不通过单元测试进行测试,但您也可以进行自动化 UI 测试,这与单元测试不同。
到目前为止,您的示例类本身并不是非常适合单元测试。MVVM 试图完成的主要事情之一(除了关注点分离)是解耦您的代码。您的 ViewModel 应该只包含表示逻辑,而不能包含业务逻辑。这进入了 MVVM 的模型层。
您的 ViewModel 是紧密耦合的,因为您正在MyCountDownTimerViewModel中实例化。因此,您不能再进行单元测试,因为每次测试ViewModel课程时,您还将测试MyCountDownTimer. 这会将您的单元测试变成集成测试(测试多个组件一起工作)。
每个定义的单元测试应该只测试一个非常特定的类型/类或某个代码块。换句话说,一个代码单元,因此得名:单元测试。为此,您需要解耦要测试的对象的依赖关系。
您通过将对象拆分为接口和实现来解耦对象,然后通常通过构造函数注入将具体实现注入到您的对象中。
例如:
public class ViewModel extends BaseObservable {
private long countDownTime;
// Use final keyword here, so mCountDownTimer can only be set in the constructor and never changed
// this enforces the the classes invariants and once initialized, you'll be sure
// that it never can be null, so no need to do null checks before using
private final MyCountDownTimerInterface mCountDownTimer;
private final String TAG = getClass().getSimpleName();
public ViewModel(MyCountDownTimerInterface mCountDownTimer) {
if(countDownTimer == null) {
throw new IllegalArgumentException("countDownTimer can't be null. ");
}
this.mCountDownTimer = countDownTimer;
}
@Bindable
public long getCountDownTime() {
return countDownTime;
}
public void setCountDownTime(long countDownTime) {
this.countDownTime = countDownTime;
notifyPropertyChanged((int) BR.countDownTime);
}
public void startCounting(Long milli) {
this.mCountDownTimer.restartTimer(milli);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以在没有类的具体实例的情况下测试您的 ViewModel MyCountDownTimer。
由于您的示例仅包含行为而没有结果测试,因此您必须在您的示例中进行行为测试,例如
startCounting(10L),则restartTimer(10L)必须被调用MyCountDownTimerInterface 并且 getCountDownTime()必须返回10L。为此,您必须模拟MyCountDownTimerInterface接口并将模拟对象传递到内部。可以设置模拟来验证模拟接口的某个方法是否使用某个参数调用。
我无法为此提供任何代码,因为我不熟悉 Java/Android Mock 框架。我是 C#/.NET 开发人员。但是,如果您不知道如何为行为驱动的单元测试模拟接口,请在 StackOverflow 上提出一个新问题:)
| 归档时间: |
|
| 查看次数: |
3521 次 |
| 最近记录: |