gpt4 book ai didi

android - 单元测试 Glide : make sure ImageView has correct image

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:20:53 26 4
gpt4 key购买 nike

Android Studio 3.0 Beta 5
robolectric:3.3.1

我有一个以下 View 持有者,它使用 glide 库加载图像 url。我正在尝试找到一种方法对此进行单元测试:

    public class MovieActorsViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.civActorPicture) CircleImageView actorPicture;
@BindView(R.id.tvName) TextView name;
@BindView(R.id.tvCharacter) TextView character;

private Context context;

public MovieActorsViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);

context = itemView.getContext();
}

public void populateActor(Actor actor) {
Glide.with(context)
.load(actor.getPicturePath())
.placeholder(R.drawable.people_placeholder)
.into(actorPicture);

name.setText(actor.getName());
character.setText(actor.getCharacter());
}
}

这是我完成的单元测试,但我不确定如何对 ImageView 进行单元测试。我不确定使用 Mockito 模拟 Glide 库是否可行?

@RunWith(RobolectricTestRunner.class)
public class MovieActorsViewHolderTest {
private MovieActorsViewHolder movieActorsViewHolder;

@Before
public void setup() {
final Context context = ShadowApplication.getInstance().getApplicationContext();
final View view = LayoutInflater.from(context).inflate(R.layout.movie_actors_item, new LinearLayout(context));

movieActorsViewHolder = new MovieActorsViewHolder(view);
}

@Test
public void testShouldPopulateActorWithValidData() {
final Actor actor = getActor();
movieActorsViewHolder.populateActor(actor);

/* test that the image view */
final ShadowDrawable shadowDrawable = Shadows.shadowOf(movieActorsViewHolder.actorPicture.getDrawable());
final Drawable drawable = Drawable.createFromPath(actor.getPicturePath());
assertThat(drawable, is(shadowDrawable.getCreatedFromResId()));

assertThat(movieActorsViewHolder.name.getText(), is(actor.getName()));
assertThat(movieActorsViewHolder.character.getText(), is(actor.getCharacter()));
}

private Actor getActor() {
return new Actor(
"https://image.tmdb.org/t/p/w92/dRLSoufWtc16F5fliK4ECIVs56p.jpg",
"Robert Danny Junior",
"Iron Man");
}

输出:

Expected: is <org.robolectric.shadows.ShadowBitmapDrawable@ffffffe0>
but: was <android.graphics.drawable.BitmapDrawable@ffffffe0>
Expected :is <org.robolectric.shadows.ShadowBitmapDrawable@ffffffe0>

Actual :<android.graphics.drawable.BitmapDrawable@ffffffe0>

非常感谢您的任何建议。

最佳答案

but I am not sure how can I unit test the image view

我认为您走错了路:您想测试 Glide 是否按预期工作。作为该图书馆的客户,这不是您的责任。 Glide 有自己的测试来验证它是否按预期工作,您应该只对您在应用程序中实现的逻辑进行单元测试。

不过,如果您仍想做类似的事情,则必须在 ViewHolder 中引入一些分离:一个负责将图像加载到 ImageView 中的组件。


public interface ImageLoader {

void load(Context context,
String path,
@DrawableRes int placeholder,
ImageView imageView);
}

谁的实现是下面的类:


public class ImageLoaderImpl implements ImageLoader {

@Override
public void load(Context context, String path, int placeholder, ImageView imageView) {
Glide.with(context)
.load(path)
.placeholder(placeholder)
.into(imageView);
}

}

现在你的 ViewHolder 会变成这样:


class MovieActorsViewHolder extends RecyclerView.ViewHolder {

@BindView(R.id.picture)
ImageView imageView;
// other views

ImageLoader imageLoader;

MovieActorsViewHolder(View itemView, ImageLoader imageLoader) {
super(itemView);
ButterKnife.bind(this, itemView);

this.imageLoader = imageLoader;
}

void populateActor(Actor actor) {
imageLoader.load(itemView.getContext(),
actor.getPicturePath(),
R.drawable.people_placeholder,
imageView);

// other actions
}

}

这将使您可以灵活地模拟 ImageLoader 类。

现在开始测试。这是设置:


@Before
public void setup() {
imageLoader = Mockito.mock(ImageLoader.class);

activity = Robolectric.setupActivity(MainActivity.class);
ViewGroup root = (ViewGroup) activity.findViewById(R.id.root);

View inflated = activity.getLayoutInflater().inflate(R.layout.item, root);
holder = new MovieActorsViewHolder(inflated, imageLoader);
}

测试方法如下:


@Test
public void test() throws InterruptedException {
final String path = "https://image.tmdb.org/t/p/w92/dRLSoufWtc16F5fliK4ECIVs56p.jpg";
final Actor actor = new Actor(path);
final Bitmap bitmap = Shadow.newInstanceOf(Bitmap.class);
final BitmapDrawable drawable = new BitmapDrawable(activity.getResources(), bitmap);

doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
holder.imageView.setImageDrawable(drawable);
return null;
}
}).when(imageLoader).load(activity, path, R.drawable.people_placeholder, holder.imageView);

holder.populateActor(actor);

assertEquals(holder.imageView.getDrawable(), drawable);
}

这会过去的。但是问问你自己:你用这个测试了什么?相反,更好的测试是确保 imageLoader.load(...) 已使用正确的参数调用,忽略 Glide 如何将图像下载到 ImageView .


I wasn't trying to test the Glide API, but only to test that the image was successfully loaded into the imageview, or maybe just make sure the glide was called with the correct parameters.

这两个语句基本上是同一件事:如果您验证您将作业委托(delegate)给 Glide 并使用正确的参数,那么它会验证 Glide 将正确加载图像。

现在,问题归结为如何验证您是否使用正确的参数将作业委托(delegate)给 Glide?

在上述场景中:


holder.populateActor(actor);

verify(imageLoader).load(activity, path, R.drawable.people_placeholder, holder.imageView);

这将检查是否使用这些参数查询了 imageLoader

just trying to find the best way to ensure the image view has an image

你想要的是创建一个抽象,它将用一些模拟的 Drawable 填充 ImageView,并且在你的测试中你将检查 ImageView 是否 实际上已经被那个 drawable 填充了。这不完全一样吗,您验证您的抽象方法是否被调用(在上述情况下 ImageLoader#load())?因此,无需显式检查 ImageView 是否被 Drawable 填充,因为它肯定会,只要您还模拟了该组件。

I guess this would mean mocking the Glide

不依赖实现,依赖抽象。如果您稍后决定从 Glide 迁移到 SomeAwesomeImageLoder 怎么办?您必须更改源代码和测试中的所有内容。

另一方面,如果您有一个负责图像加载的类,您只需将加载逻辑封装在该类中,因此只有该类需要更改。此外,这为执行单元测试提供了完美的接缝。

关于android - 单元测试 Glide : make sure ImageView has correct image,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46251526/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com