如何使用mock()和spy()测试静态方法

时间:2017-09-18 10:23:54

标签: android unit-testing junit mockito powermockito

代码部分中的以下发布方法包含一个静态方法,即" with()"。我想测试下面的代码,所以我编写了这个方法的测试 如测试部分所示。

我尝试使用" spy()"和" mock()"但测试失败了alwyas。

请让我知道如何测试方法返回void?

public class ValidationTest {
@Mock
private Context mCtx = null;
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();

@Before
public void setUp() throws Exception {
    mCtx = Mockito.mock(Context.class);
    Assert.assertNotNull("Context is not null", mCtx);
}

 @Test
public void whenRequestCreatorFromUrlTest() throws Exception {
    Picasso picasso = Picasso.with(mCtx);
    Picasso spyPicasso = spy(picasso);
    Uri mockUri = mock(Uri.class);
    RequestCreator requestCreator = Picasso.with(mCtx).load(mockUri);
    RequestCreator spyRequestCreator = spy(requestCreator);

    doReturn(spyRequestCreator).when(spyPicasso.load(mockUri));
    //when(spyPicasso.load(mockUri)).thenReturn(spyRequestCreator);
    RequestCreator actual = spyPicasso.load(mockUri);

    Assert.assertEquals(requestCreator, actual);
}

测试

{{1}}

2 个答案:

答案 0 :(得分:6)

通常情况下,如果你最终使用PowerMock,那么这是一个很好的迹象,表明你很可能是错误的。

如果您不是直接引用Picasso而是创建一个组件,而不是直接引用ImageLoader,那么该组件的责任是加载图片,让我们说类Glide。这会给你什么?

  • 关注点分离:如果明天您决定转到Picasso,则不应该更改您使用ImageLoader的每个班级,您只需更改 class ImageLoader { RequestCreator load(String url); } 。其他组件对这些更改并不了解,因为它们依赖于抽象,

  • Seam:这将允许您轻松模拟依赖项以执行单元测试

这将是我们的抽象:


    class ImageLoaderImpl implements ImageLoader {

        private final Picasso picasso;

        public ImageLoader(Context context) {
            this.picasso = Picasso.with(context);
        }

        @Overrides
        public RequestCreator load(String url) {
            return picasso.load(url);
        }
    }

让我们提供一个实现:

Picasso

现在,只要您需要ImageLoader使用 public RequestCreator requestCreatorFromUrl(String picUrl) { return imageLoader.load(picUrl); } ,就可以在您的组件中使用

因此,您的方法如下:


    @Test
    public void test() {
        ImageLoader imageLoader = Mockito.mock(ImageLoader.class);
        RequestCreator expected = Mockito.mock(RequestCreator.class);
        String TEST_URL = "https://www.some.url/img.jpg";

        when(imageLoader.load(TEST_URL)).thenReturn(expexted);

        RequestCreator actual = clazzToTest.requestCreatorFromUrl(TEST_URL);

        assertEquals(expected, actual);
    }

然后您的测试将如下所示:

static

不要嘲笑PowerMock方法,不需要Full Keyboard Access

答案 1 :(得分:3)

来自Mockito's FAQ

  

Mockito有哪些限制

     

...

     

无法模拟静态方法

请改用PowerMockHere您将找到有关如何模拟静态方法的详细说明。

<强>更新

要将 PowerMock 应用于您的测试,您需要:

  • 在测试级别添加@PrepareForTest

    @PrepareForTest(Picasso.class) public class ValidationTest { ... }

  • 调用PowerMockito.mockStatic()来模拟静态类

    PowerMockito.mockStatic(Picasso.class);

  • 只需使用Mockito.when()来设定您的期望:

    Mockito.when(Picasso.with(mCtx)).thenReturn(requestCreator);

同一组步骤适用于RequestCreator.class

P.S。我可以犯错误,因为我不知道您使用的第三方库的API。