简体   繁体   English

如何使用JUnit和Mockito模拟内部逻辑

[英]How to use JUnit and Mockito to mock inner logic

I'm kind of new to Junit and Mockito and trying to understand how to mock parts of logic of a class. 我是Junit和Mockito的新手,试图了解如何模拟类的逻辑。

I have a method which does a http post and get call, but it might be a DB lookup. 我有一个方法可以执行http发布并获取调用,但是它可能是数据库查找。 How do I mock the response from the HTTP call in this method 如何在此方法中模拟来自HTTP调用的响应

  BufferedReader in = new BufferedReader(new InputStreamReader(httpsConnection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();

while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}

I mean there must a way to test my logic without doing to real http call or db lookup or whatever. 我的意思是必须有一种方法可以测试我的逻辑,而无需执行真正的http调用或db查找或其他操作。

// HTTP GET request
public String sendGet(URL url) throws Exception {

    s_logger.debug("URL: " + url);
    HttpsURLConnection httpsConnection = (HttpsURLConnection) url.openConnection();

    // Add request header
    httpsConnection.setRequestMethod("GET");
    httpsConnection.setRequestProperty("Content-Type", "application/xml");

    if (sessionId != null) {
        httpsConnection.setRequestProperty("sessionId", sessionId);
    } else {
        httpsConnection.setRequestProperty("username", ACCOUNT_USERNAME);
        httpsConnection.setRequestProperty("password", ACCOUNT_PASSWORD);
    }

    httpsConnection.setInstanceFollowRedirects(false);
    httpsConnection.setUseCaches(false);

    // Print Request Header
    s_logger.debug("Request Header: " + httpsConnection.getRequestProperties());

    int responseCode = httpsConnection.getResponseCode();
    s_logger.debug("Response Code : " + responseCode);

    Map<String, List<String>> headerFields = httpsConnection.getHeaderFields();
    s_logger.debug("Response Header: " + headerFields);

    BufferedReader in = new BufferedReader(new InputStreamReader(httpsConnection.getInputStream()));
    String inputLine;
    StringBuilder response = new StringBuilder();

    while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
    }
    in.close();

    // Set Session ID
    final String SESSION_KEY = "sessionId";
    if (this.sessionId == null && httpsConnection.getHeaderFields().containsKey(SESSION_KEY)) {
        this.sessionId = httpsConnection.getHeaderFields().get(SESSION_KEY).get(0);
        s_logger.debug("SESSION ID : " + this.sessionId);
    }

    // print result
    s_logger.debug("RESPONSE: " + response.toString());
    return response.toString();
}

Thanks for any help or suggestion. 感谢您的帮助或建议。

UPDATE: I did kind of that has been suggested but I'm not sure if this makes sense, also I don't like the fact that these methods are now public. 更新:我确实提出了那种建议,但是我不确定这是否有意义,而且我不喜欢这些方法现在是公开的事实。

    final URL url = new URL("https://test.com");
    final String request = "Test";
    HttpsURLConnection httpsConnection = mock(HttpsURLConnection.class);


    final HttpConnectionClient httpSpy = spy(new HttpConnectionClient());
    Mockito.doReturn(httpsConnection).when(httpSpy).getConnection(url);
    Mockito.doNothing().when(httpSpy).sendRequest(httpsConnection, request);
    Mockito.doReturn(response).when(httpSpy).createBufferReader(httpsConnection);

    assertEquals(response,httpSpy.sendPost(url, request));

One hack is using spy and package-local methods: 一种技巧是使用间谍和程序包本地方法:

public  class MyClass {
     public void myMethod() {
         //stuff
         stuffThatNeedsStubbing();
         //more stuff
     }

     void stuffThatNeedsStubbing() {
         //stuff that needs stub
     }
}

public class MyClassTest {
    @Test
    public void example() {
        final MyClass myClass = spy(new MyClass());
        doNothing().when(myClass).stuffThatNeedsStubbing();
        myClass.myMethod();
    }
}

In your case, you could create a package-local method BufferedReader createBufferedReader() , and replace this with a mock in your test. 在您的情况下,您可以创建一个程序包本地方法BufferedReader createBufferedReader() ,并在测试中将其替换为模拟。

The only tricky bit is the url.openConnection() because the URL is final class, so you cannot mock it. 唯一棘手的是url.openConnection()因为URL是最终类,因此您无法对其进行模拟。 If you separate it, then you could use mock(HttpsURLConnection.class) using mockito and provide eg ByteArrayInputStream for the getInputStream() with mock-result. 如果将其分开,则可以使用带有模拟结果的mock(HttpsURLConnection.class)并为具有模拟结果的getInputStream()提供例如ByteArrayInputStream

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM