使用Mockito进行模拟注射 - Android

时间:2013-08-13 05:54:53

标签: android mockito

我刚开始在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;
}
}

2 个答案:

答案 0 :(得分:3)

  1. 由于您已经使用了@Mock for Vars类,因此无需使用 -

    mockVar = mock(Vars.class);

  2. 您需要在模拟对象上存根调用。而不是 -

    mockVar.setn1(20); mockVar.setn2(40);

  3. 你需要存根你的getter(我相信在Vars类中会有像getn1()这样的方法) -

    Mockito.when(mockVar.getn1()).thenReturn(20);
    Mockito.when(mockVar.getn2()).thenReturn(40);
    

    然后写下你的测试。

答案 1 :(得分:0)

这是人们混淆Mockito引入的部分嘲笑概念的经典问题。

你需要在Activity中注入这个模拟的Var依赖项,这很难,因为Android正在管理活动的整个生命周期。 因此,为了实现您期望的结果,您可以使用Square中的Dagger框架,或者如果您不想在应用中引入第三方依赖项,则使用服务定位器模式。

以下是有关在Activity中注入依赖项的服务定位器模式的更详细文章:Improving Android Testing with Service Locator Pattern