【问题标题】:powermock contains() not workingpowermock contains() 不工作
【发布时间】:2017-10-21 17:22:04
【问题描述】:

我正在尝试使用 PowerMockito 模拟 http 调用,但我在使用 contains() 函数时遇到了一些问题。 我的计划是检查路径是否包含某个字符串,然后返回模拟对象。 所以我有以下功能:

import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*;
import static org.mockito.Matchers.*;
import static org.mockito.internal.verification.VerificationModeFactory.times;
import static org.powermock.api.mockito.PowerMockito.*;
private static <T> void mockResponse(Class<T> type, T response, String pathContains) throws Exception
{
    mockStatic(ClientBuilder.class);
    Client client = mock(Client.class);
    when(ClientBuilder.class, "newClient").thenReturn(client);
    WebTarget webTarget = mock(WebTarget.class);
    when(client.target(anyString())).thenReturn(webTarget);

    //This is what doesn't work
    when(webTarget.path(contains(pathContains))).thenReturn(webTarget);

    when(webTarget.queryParam(any(), any())).thenReturn(webTarget);
    Invocation.Builder invocationBuilder = mock(Invocation.Builder.class);
    when(webTarget.request()).thenReturn(invocationBuilder);
    Invocation invocation = mock(Invocation.class);
    when(invocationBuilder.buildGet()).thenReturn(invocation);

    Response res = mock(Response.class);
    when(invocation.invoke()).thenReturn(res);
    when(res.readEntity(type)).thenReturn(response);
}

mockResponse(GenreList.class, new GenreList(new Genre(0, "g")), "genre");

问题是我在尝试进行 HTTP 调用时得到一个空指针:

    Response res = client.target(theMovieDbURL)
                         .path("/3/genre/movie/list")
                         .queryParam("api_key", apiKey)
                         .request()
                         .buildGet()
                         .invoke();

如果我在哪里将模拟从contains() 更改为anyString(),它就像一个魅力,但我需要对不同的路径有不同的响应,所以我不能将它保留为anyString()。我也尝试将其更改为eq(),但它也不起作用。

我在这里缺少什么?

来自我的毕业生:

testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '1.6.6'
testCompile group: 'org.powermock', name: 'powermock-api-mockito', version: '1.6.6'
testCompile group: 'org.powermock', name: 'powermock-module-junit4-rule', version: '1.6.6'

【问题讨论】:

  • 请提供您测试的模拟准备部分。您共享的代码中没有调用mockResponse
  • @AlehMaksimovich 现在就在那里 :)
  • 我现在唯一的想法是您可能使用了错误的contains。您可以添加静态导入部分吗?
  • 有趣的是我无法重现您的问题。 when(webTarget1.path(contains("genre"))).thenReturn(webTarget1); 以及 doReturn(webTarget2).when(webTarget2).path(contains("genre"));when(webTarget3.path(matches(".*genre.*"))).thenReturn(webTarget3); 对我来说一切都有效。最后一个问题,您使用的是哪个版本的 PowerMock 和 Mockito?
  • 这真的很奇怪......我已经从我的 gradle 文件中附加了部分。你用的是什么版本?

标签: java testing mocking powermock


【解决方案1】:

更多的是非答案:你在这里走错了兔子洞。

事情是:测试的目的是确保特定生产代码实现测试应该涵盖的要求。没有其他的。

导致:您更喜欢多个简单、直接的测试,而不是能够处理许多不同方面的单个代码。

意思:你不要去开始使用

when(webTarget.path(contains(pathContains))).thenReturn(webTarget);

你有各种不同的可能性 contains() 可能会看到。相反,你宁愿有 n 个测试明确说明

when(webTarget.path(contains(A))).thenReturn(webTargetA);

...

when(webTarget.path(contains(B))).thenReturn(webTargetB);

换句话说:您打算在测试代码中以某种方式表达巧妙的“业务逻辑”。你想让它“聪明”。不要那样做。而是专注于编写测试代码,如前所述,直接创建一个特定的设置,然后测试一个的东西。

换句话说:您的测试代码中应该没有需要提供参数特定的返回值。因为定义了您的生产代码将看到的设置(以及路径)。您告诉它在一个测试中采用路径 A,在另一个测试中采用路径 B。然后,您想要详细说明 if/then 逻辑的愿望就烟消云散了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    • 2015-11-28
    • 2019-07-24
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    • 2012-06-14
    相关资源
    最近更新 更多