6

我有一个测试方法,开始如下:

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
    contextString = adapter.getItem(info.position);
        /.../
    }

我想使用 Mockito 对其进行测试,但是如果我这样声明 menuInfo:

@Mock ContextMenuInfo menuInfo

那么我无法编译以下语句:

Mockito.when(menuInfo.position).thenReturn(1);

因为它对对象无效ContextMenuInfo。我不能将我的对象声明为AdapterView.AdapterContextMenuInfo类,因为那时我在运行时出现错误。

我知道在 Mockito 中,模拟可能实现多个接口,但同样不适用于类。如何测试我上面显示的方法?

4

3 回答 3

4

Mockito 通过使用 Java继承来替换类上方法的实现来工作。但是,它看起来像是position一个字段on AdapterContextMenuInfo,这意味着 Mockito 无法为您模拟它。

幸运的是,AdapterContextMenuInfo 有一个公共构造函数,因此您不必模拟它——您可以为测试创建一个并将其传递给您的方法。

@Test public void contextMenuShouldWork() {
  ContextMenuInfo info =
      new AdapterView.AdapterContextMenuInfo(view, position, id);
  systemUnderTest.onCreateContextMenu(menu, view, info);

  /* assert success here */
}

如果您曾经因无法直接模拟或实例化的类而陷入这种模式,请考虑创建一个可以模拟的辅助类:

class MyHelper {

  /** Used for testing. */
  int getPositionFromContextMenuInfo(ContextMenuInfo info) {
    return ((AdapterContextMenuInfo) info).position;
  }
}

现在您可以重构您的视图以使用它:

public class MyActivity extends Activity {
  /** visible for testing */
  MyHelper helper = new MyHelper();

  public void onCreateContextMenu(
      ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    int position = helper.getPositionFromContextMenuInfo(menuInfo);
    // ...
  }
}

...然后在您的测试中模拟助手。

/** This is only a good idea in a world where you can't instantiate the type. */
@Test public void contextMenuShouldWork() {
  ContextMenuInfo info = getSomeInfoObjectYouCantChange();

  MyHelper mockHelper = Mockito.mock(MyHelper.class);
  when(mockHelper.getPositionFromContextMenu(info)).thenReturn(42);
  systemUnderTest.helper = mockHelper;
  systemUnderTest.onCreateContextMenu(menu, view, info);

  /* assert success here */
}    

还有另一种选择,涉及重构:

public class MyActivity extends Activity {
  public void onCreateContextMenu(
      ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    AdapterView.AdapterContextMenuInfo info =
        (AdapterView.AdapterContextMenuInfo) menuInfo;
    onCreateContextMenuImpl(info.position);
  }

  /** visible for testing */
  void onCreateContextMenuImpl(int position) {
    // the bulk of the code goes here
  }
}

@Test public void contextMenuShouldWork() {
  systemUnderTest.onCreateContextMenuImpl(position);

  /* assert success here */
}
于 2013-08-09T21:46:18.143 回答
4

可能是使用 mockito 的extraInterfaces选项

        @Mock(extraInterfaces=AdapterView.AdapterContextMenuInfo.class) 
        ContextMenuInfo menuInfo

然后像这样嘲笑它

Mockito.doReturn(1).when((AdapterView.AdapterContextMenuInfo)menuInfo).position
于 2016-04-26T08:27:30.563 回答
0

为什么你没有一个AdapterView.AdapterContextMenuInfo让你写作的吸气剂info.getPosition()?如果你有,那么你可以模拟AdapterView.AdapterContextMenuInfo,存根getPosition(),然后只需将模拟传递给你正在测试的方法。

于 2013-08-10T23:54:11.607 回答