如何在我们想使用 Junit 和 Mockito 实现单元测试的另一个 class 方法中模拟 class 方法?

How to mock class methods inside another class methods which we would like to implement unit test using Junit and Mockito?

我的代码总结了 3 件事:

这是我想为 if-else 条件实施单元测试的方法:

public String checkYarnApplications() throws IOException {

    String infoMessage = null;

    ObjectGetter objectGetter = new ObjectGetter(getUrlAddress());

    JSONObject j = objectGetter.objectGetter();

    // Initialize stringbuilder to build slack message
    StringBuilder stringBuilder = new StringBuilder();

    // Iterate through number of existing yarn application
    for (int i = 0; i < j.getJSONObject("apps").getJSONArray("app").length(); i++){

        JSONObject name = j.getJSONObject("apps")
                .getJSONArray("app")
                .getJSONObject(i);

        String state = name.get("state").toString();

        // Check if application is in Running state
        if (state.equals("RUNNING")){

            // Get elapsed time for each running application and convert it to hour
            int elapsed_time = name.getInt("elapsedTime")/3600000;
            // Get application name
            String app_name = name.get("name").toString();
            // Get application queue_name
            String queue_name = name.get("queue").toString();
            // Get application user_name
            String user_name = name.get("user").toString();

            // Check if pyspark applications last longer than specified time in config.properties
            if (app_name.startsWith("pyspark-shell") && elapsed_time > getSparkCheckTime()){
                String app_id = name.get("id").toString();
                String infoMessageSpark = "pyspark application " + app_id + " has been killed because it takes longer than " +
                        getSparkCheckTime() + " hours. Elapsed Time:" + elapsed_time + " hours";
                infoMessage = infoMessageSpark;
                logger.info(infoMessageSpark);
                logger.info(name.toString());
                // Kill yarn application
                AppKiller appKiller = new AppKiller(String.format("%s%s/state?user.name=atlasapp",getUrlAddress(),app_id));
                appKiller.appKiller();
                // Add info message to slackmessage string builder
                stringBuilder.append(infoMessageSpark);
                stringBuilder.append("\n");
            }
            // Check if self_bi applications last longer than specified time in config.properties
            else if (!queue_name.equals("yarn-system") && !queue_name.equals("hudi") && !queue_name.equals("hepsistream") &&
                    !app_name.equals("Bzip2Hdfs") && !user_name.equals("spark") && !user_name.equals("yarn-ats") &&
                    !app_name.startsWith("pyspark-shell") && !queue_name.equals("llap") && elapsed_time > getappCheckTime()){
                String app_id = name.get("id").toString();
                String infoMessageSb = queue_name + " application, " + app_id + " has been killed because it takes longer than "
                        + getappCheckTime() + " hours. Elapsed Time:" + elapsed_time + " hours";
                infoMessage = infoMessageSb;
                logger.info(infoMessageSb);
                logger.info(name.toString());
                // Kill yarn application
                AppKiller appKiller = new AppKiller(String.format("%s%s/state?user.name=atlasapp",getUrlAddress(),app_id));
                appKiller.appKiller();
                // Add info message to slackmessage string builder
                stringBuilder.append(infoMessageSb);
                stringBuilder.append("\n");
            }
            // Check if any application except hudi, llap last longer than specified time in config.properties and send them to slack channel
            else if (!queue_name.equals("hudi") && !queue_name.equals("llap") && !queue_name.equals("hepsistream") &&
                    !queue_name.equals("yarn-system") && !user_name.equals("yarn-ats") &&
                    !app_name.startsWith("pyspark-shell") && !app_name.equals("Bzip2Hdfs") && !user_name.equals("spark") &&
                    elapsed_time > getCheckTime()){
                logger.info("Application_id: " + name.get("id").toString() + " is running longer than " +  getCheckTime() + " hours");
                String textMessage ="Elapsed time: " + elapsed_time + " hours" + ", " +
                        "Application_Id: " + name.get("id").toString() + ", " +
                        "Username: " + name.get("user").toString() + ", " +
                        "Queuename:" + name.get("queue").toString() + ", " +
                        "Usage:" + name.get("clusterUsagePercentage").toString();
                stringBuilder.append(textMessage);
                stringBuilder.append("\n");
            }
        }

    }
}

关于代码的一些说明:

  1. ObjectGetter 是另一个 class 创建用于使用 http 连接 Json 对象
  2. Appkiller 是另一个 class 创建的,用于在满足条件时使用 put 请求杀死某些应用程序

我试图模拟它们,并且只使用下面的测试代码测试 if-else 条件:

class YarnModelTest {

private YarnModel yarnModel;
private static final ObjectGetter objectGetter = mock(ObjectGetter.class);
private static final AppKiller appKiller = mock(AppKiller.class);

@Before
public void setup() throws IOException {
    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    try (InputStream input = classloader.getResourceAsStream("config.properties")) {

        Properties properties = new Properties();

        // load a properties file
        properties.load(input);
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> map = mapper.readValue(properties.getProperty("jsonString"), Map.class);
        Scenerio scenerio = new Scenerio(map);
        when(objectGetter.objectGetter()).thenReturn((JSONObject) scenerio.getJsonObject());
        Mockito.doNothing().when(objectGetter).objectGetter();
        Mockito.doNothing().when(appKiller).appKiller();

    }
}

@Test
void checkSparkCheckTime() {
    YarnModel yarnModel = new YarnModel("http://localhost:8080", 24, 48, 24, "http://localhost:7070");
    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    try (InputStream input = classloader.getResourceAsStream("config.properties")) {

        Properties properties = new Properties();

        // load a properties file
        properties.load(input);
        String test = properties.getProperty("sparkTest");
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> map = mapper.readValue(properties.getProperty("jsonString"), Map.class);
        assertEquals(test, yarnModel.checkYarnApplications());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

关于测试代码的一些说明:

  1. 用于获取预定义的属性json单元测试中的字符串形式比较
  2. yarnModel.checkYarnApplications() 方法 returns 根据条件的一些字符串,我只想检查它们是否相等。

问题:

我遇到了以下错误,据我所知,我的模拟不正确,代码仍在尝试创建 http 连接。任何建议将不胜感激

java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:607)
at java.net.Socket.connect(Socket.java:556)
at sun.net.NetworkClient.doConnect(NetworkClient.java:180)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:463)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:558)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:242)
at sun.net.www.http.HttpClient.New(HttpClient.java:339)
at sun.net.www.http.HttpClient.New(HttpClient.java:357)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1223)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1162)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1056)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:990)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1567)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1495)
at java.net.URL.openStream(URL.java:1093)
at com.fasterxml.jackson.core.TokenStreamFactory._optimizedStreamFromURL(TokenStreamFactory.java:211)
at com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:1055)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3561)
at com.hepsiburada.Utils.ObjectGetter.objectGetter(ObjectGetter.java:33)
at com.hepsiburada.Model.YarnModel.checkYarnApplications(YarnModel.java:77)
at com.hepsiburada.Model.YarnModelTest.checkSparkCheckTime(YarnModelTest.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod[=14=](ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke[=14=](ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute[=14=](EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

我将模拟从 @Before 注释转移到 @Test 注释内部,现在一切似乎都正常了。下面请看开发成功的测试代码:

    class YarnModelTest {

    private YarnModel yarnModel;
    private static final ObjectGetter objectGetter = mock(ObjectGetter.class);
    private static final AppKiller appKiller = mock(AppKiller.class);


    @Test
    void checkSparkCheckTime() {
        YarnModel yarnModel = new YarnModel("http://localhost:8088/ws/v1/cluster/apps/", 24, 48, 24, "http://localhost:7070");
        ClassLoader classloader = Thread.currentThread().getContextClassLoader();
        try (InputStream input = classloader.getResourceAsStream("configuration.properties")) {

            Properties properties = new Properties();

            // load a properties file
            properties.load(input);
            String test = properties.getProperty("sparkTest");
            ObjectMapper mapper = new ObjectMapper();
            String json = properties.getProperty("jsonString");
            Map<String, Object> map = new HashMap<>();

            map = mapper.readValue(json, new TypeReference<Map<String, Object>>(){});
            JSONObject jsonobject = new JSONObject(map);

            when(objectGetter.objectGetter()).thenReturn(jsonobject);
            Mockito.doNothing().when(objectGetter).setUrlObjectString("http://atlasm03.infoshop.com.tr:8088/ws/v1/cluster/apps/");
            Mockito.doNothing().when(appKiller).appKiller();
            assertEquals(test,yarnModel.checkYarnApplications(objectGetter));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}