【发布时间】:2013-08-13 05:54:52
【问题描述】:
我刚刚开始在 Android 上进行单元测试。我试过测试一个简单的计算器应用程序,但遇到了一个关于注入模拟的问题。
据我了解,有两种注入模拟的方法。使用依赖注入或使用 @Mock 和 @InjectMocks 等注解。
这是我的问题:
我的计算器类使用另一个类Vars,它保存我打算使用的变量的默认值。这是我要模拟的类,以便我可以使用其他变量而不是默认变量。
@RunWith(MockitoJUnitRunner.class)
public class CalcActivityTest extends ActivityUnitTestCase<CalcActivity> {
private Intent in;
private Button btnAdd,btnSub,btnMul,btnDiv,btnDef;
private TextView res;
@InjectMocks
private CalcActivity mActivity;
@Mock
private Vars mockVar;
public CalcActivityTest() {
super(CalcActivity.class);
}
@Before
protected void setUp() throws Exception{
super.setUp();
in = new Intent(getInstrumentation().getTargetContext(),CalcActivity.class);
in.putExtra("num1", 20.0);
in.putExtra("num2",20.0);
startActivity(in, null, null);
mockVar = mock(Vars.class);
mockVar.setn1(20);
mockVar.setn2(40);
mActivity = getActivity();
}
但是,当我尝试对任何操作使用 mockVar 时,会使用存储在 Vars 中的默认值而不是 mockVar,这可能意味着模拟变量没有正确注入。谁能指出我哪里出错了?
编辑:使用 CalcActivity 中的代码更新问题
package com.example.advancedcalc;
import com.example.advancedcalc.R;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class CalcActivity extends Activity implements OnClickListener {
private Button btnAdd,btnSub,btnMul,btnDiv,btnDefault;
private TextView res;
private double n1,n2;
private Vars var;
public CalcActivity(Vars var){
this.var = var;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calc);
btnAdd = (Button) findViewById(R.id.add);
btnSub = (Button) findViewById(R.id.sub);
btnMul = (Button) findViewById(R.id.mul);
btnDiv = (Button) findViewById(R.id.div);
btnDefault = (Button) findViewById(R.id.btnDef);
res = (TextView) findViewById(R.id.res);
Bundle extras = getIntent().getExtras();
n1 = extras.getDouble("num1");
n2 = extras.getDouble("num2");
var = new Vars();
btnAdd.setOnClickListener(this);
btnSub.setOnClickListener(this);
btnMul.setOnClickListener(this);
btnDiv.setOnClickListener(this);
btnDefault.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.calc, menu);
return true;
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.add:
res.setText(String.valueOf(add(n1,n2)));
break;
case R.id.sub:
res.setText(String.valueOf(sub(n1,n2)));
break;
case R.id.mul:
res.setText(String.valueOf(mul(n1,n2)));
break;
case R.id.div:
res.setText(String.valueOf(div(n1,n2)));
break;
case R.id.btnDef:
n1 = var.getn1();
n2 = var.getn2();
}
}
public double add(double n1,double n2){
return n1+n2;
}
public double sub(double n1,double n2){
return n1-n2;
}
public double mul(double n1,double n2){
return n1*n2;
}
public double div(double n1,double n2){
return n1/n2;
}
}
【问题讨论】:
-
CalcActivity的代码是什么?为什么要在 setUp() 方法中为 mockVars 重新分配一个新的模拟,因为 Mock 注释已经创建了一个?
getActivity()是做什么的? -
getActivity()返回被测活动。我正在重新分配 mockVars 因为mockVar.set()在没有它的情况下返回一个空指针异常。使用 CalcActivity 中的代码更新问题。 -
被测活动应该是
mActivity,因为这是 Mockito 用mockVar注入的(在你在 setUp() 方法中重新初始化它之前创建的那个)。重新阅读这些注释的文档。您不应该对这些变量重新产生任何影响,否则注释将没有任何用途。 -
我需要使用
getActivity(),因为我需要调用findViewById()方法来初始化我的CalcActivity 类中的不同UI 元素。不使用getActivity()会为我的所有 UI 元素返回一个空指针异常。 -
那么你应该注入模拟 UI 元素,或者在 getActivity() 返回的真实活动上创建一个 Spy,而不是模拟。