使用 Robolectric 2.X 创建自定义阴影
Creating custom shadows with Robolectric 2.X
我的项目是 运行 Robolectric 2.x(2.4)。我按照官方文档中的示例创建了我自己的自定义阴影 class 但是 Robolectric 没有使用它。
项目在 GitHub(branch roboMockitoTutorial)。以下是部分代码:
我尝试创建影子的 class(AppUtils):
package com.jiahaoliuliu.robolectricsample;
/**
* Created by jiahao on 2/15/15.
*/
public class AppUtils {
public AppUtils() {}
public int generateNumberUsersRandomly() {
// :)
return 42;
}
}
Activity 其中 class 被使用:
package com.jiahaoliuliu.robolectricsample;
import android.graphics.Bitmap;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.IOException;
import java.io.OutputStream;
public class MainActivity extends ActionBarActivity {
TextView my_hello_text_view;
Button mClickMeBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppUtils appUtils = new AppUtils();
System.out.println("The randomly generated number of users is " + appUtils.generateNumberUsersRandomly());
setContentView(R.layout.activity_main);
my_hello_text_view = (TextView) findViewById(R.id.my_hello_text_view);
mClickMeBtn = (Button) findViewById(R.id.clickMeBtn);
int w = 200, h = 200;
Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
Bitmap bmp = Bitmap.createBitmap(w, h, conf); // this creates a MUTABLE bitmap
bmp.compress(Bitmap.CompressFormat.PNG, 200, new OutputStream() {
@Override
public void write(int oneByte) throws IOException {
System.out.println("Writting in the outputStream " + oneByte);
}
});
}
public void clickMeBtnPressed(View view) {
my_hello_text_view.setText(getString(R.string.ok_thanks));
}
}
影子class(AppUtilsShadow):
package com.jiahaoliuliu.robolectricsample;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.shadows.ShadowView;
/**
* Created by jiahao on 2/15/15.
*/
@Implements(AppUtils.class)
public class AppUtilsShadow {
@RealObject
private AppUtils appUtils;
public AppUtilsShadow() {}
// Trying to create the constructor for it.
public void __constructor__() {}
@Implementation
public int generateNumberUsersRandomly() {
System.out.println("Invoking the real object method");
return appUtils.generateNumberUsersRandomly();
}
}
测试class:
package com.jiahaoliuliu.robolectricsample;
import com.jiahaoliuliu.robolectricsample.MainActivity;
import com.jiahaoliuliu.robolectricsample.RobolectricGradleTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.List;
import static org.assertj.android.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@RunWith(RobolectricGradleTestRunner.class)
@Config(shadows = {AppUtilsShadow.class, MyShadowBitmap.class})
public class MyActivityTest {
private MainActivity mActivity;
@Before
public void setup() {
mActivity = Robolectric.buildActivity(MainActivity.class).create().get();
}
@Test
public void testMyActivityAppearsAsExpectedInitially() {
assertThat(mActivity.my_hello_text_view).isVisible();
assertThat(mActivity.my_hello_text_view).hasText("Hello world!");
assertThat(mActivity.mClickMeBtn).hasText("Click Me");
}
}
Shadows 的问题在于它们用于遮蔽 Android classes,而不是所有 classes。参见 documentation or even better, the code。
由于 AppUtils 不是来自 Android SDK,因此您的影子不会被拾取。
这不是缺陷,据我所知,这是设计有意做出的决定。由于这是您自己的 class,您可以使用更好的方法来加载测试 class,并且不需要阴影。
就是说,如果你真的想为此使用阴影,你可以创建一个自定义测试运行器,你可以在其中覆盖 shouldInstrument
以使其也检测你正在使用的 classes 或包感兴趣。然后,您上面的代码应该可以工作。我从未尝试过此操作,但您可以查看 this 以获取一些示例代码。
我的项目是 运行 Robolectric 2.x(2.4)。我按照官方文档中的示例创建了我自己的自定义阴影 class 但是 Robolectric 没有使用它。
项目在 GitHub(branch roboMockitoTutorial)。以下是部分代码:
我尝试创建影子的 class(AppUtils):
package com.jiahaoliuliu.robolectricsample;
/**
* Created by jiahao on 2/15/15.
*/
public class AppUtils {
public AppUtils() {}
public int generateNumberUsersRandomly() {
// :)
return 42;
}
}
Activity 其中 class 被使用:
package com.jiahaoliuliu.robolectricsample;
import android.graphics.Bitmap;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.IOException;
import java.io.OutputStream;
public class MainActivity extends ActionBarActivity {
TextView my_hello_text_view;
Button mClickMeBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppUtils appUtils = new AppUtils();
System.out.println("The randomly generated number of users is " + appUtils.generateNumberUsersRandomly());
setContentView(R.layout.activity_main);
my_hello_text_view = (TextView) findViewById(R.id.my_hello_text_view);
mClickMeBtn = (Button) findViewById(R.id.clickMeBtn);
int w = 200, h = 200;
Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
Bitmap bmp = Bitmap.createBitmap(w, h, conf); // this creates a MUTABLE bitmap
bmp.compress(Bitmap.CompressFormat.PNG, 200, new OutputStream() {
@Override
public void write(int oneByte) throws IOException {
System.out.println("Writting in the outputStream " + oneByte);
}
});
}
public void clickMeBtnPressed(View view) {
my_hello_text_view.setText(getString(R.string.ok_thanks));
}
}
影子class(AppUtilsShadow):
package com.jiahaoliuliu.robolectricsample;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.shadows.ShadowView;
/**
* Created by jiahao on 2/15/15.
*/
@Implements(AppUtils.class)
public class AppUtilsShadow {
@RealObject
private AppUtils appUtils;
public AppUtilsShadow() {}
// Trying to create the constructor for it.
public void __constructor__() {}
@Implementation
public int generateNumberUsersRandomly() {
System.out.println("Invoking the real object method");
return appUtils.generateNumberUsersRandomly();
}
}
测试class:
package com.jiahaoliuliu.robolectricsample;
import com.jiahaoliuliu.robolectricsample.MainActivity;
import com.jiahaoliuliu.robolectricsample.RobolectricGradleTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.List;
import static org.assertj.android.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@RunWith(RobolectricGradleTestRunner.class)
@Config(shadows = {AppUtilsShadow.class, MyShadowBitmap.class})
public class MyActivityTest {
private MainActivity mActivity;
@Before
public void setup() {
mActivity = Robolectric.buildActivity(MainActivity.class).create().get();
}
@Test
public void testMyActivityAppearsAsExpectedInitially() {
assertThat(mActivity.my_hello_text_view).isVisible();
assertThat(mActivity.my_hello_text_view).hasText("Hello world!");
assertThat(mActivity.mClickMeBtn).hasText("Click Me");
}
}
Shadows 的问题在于它们用于遮蔽 Android classes,而不是所有 classes。参见 documentation or even better, the code。
由于 AppUtils 不是来自 Android SDK,因此您的影子不会被拾取。
这不是缺陷,据我所知,这是设计有意做出的决定。由于这是您自己的 class,您可以使用更好的方法来加载测试 class,并且不需要阴影。
就是说,如果你真的想为此使用阴影,你可以创建一个自定义测试运行器,你可以在其中覆盖 shouldInstrument
以使其也检测你正在使用的 classes 或包感兴趣。然后,您上面的代码应该可以工作。我从未尝试过此操作,但您可以查看 this 以获取一些示例代码。