java—单元测试的问题:junit和mockito框架

f0brbegy  于 2021-08-25  发布在  Java
关注(0)|答案(1)|浏览(428)

我正在学习使用junit和mockito框架进行单元测试和双重测试,但是在使用“mocks”的特定测试中,我没有得到预期的结果。我做一个 assertThat 它应该返回阳性测试,相反,它返回的错误是 Mockito cannot mock this class . 它是一个名为“控制台”的类,必须打印和收集值​​从用户的键盘,但当然,在单元测试中,这应该是“模拟”的,以避免在反模式中的“干预测试”,即测试向开发人员请求数据,也就是说,我需要“模拟”用户输入。这个“控制台”类类似于典型java bufferedreader类的一个小外观。
我通过了相关课程:
慰问:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Console {

    private BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

    public String readString(String title) {
        String input = null;
        boolean ok = false;
        do {
            this.write(title);
            try {
                input = this.bufferedReader.readLine();
                ok = true;
            } catch (Exception ex) {
                this.writeError("characte string");
            }
        } while (!ok);
        return input;
    }

    public int readInt(String title) {
        int input = 0;
        boolean ok = false;
        do {
            try {
                input = Integer.parseInt(this.readString(title));
                ok = true;
            } catch (Exception ex) {
                this.writeError("integer");
            }
        } while (!ok);
        return input;
    }

    public char readChar(String title) {
        char charValue = ' ';
        boolean ok = false;
        do {
            String input = this.readString(title);
            if (input.length() != 1) {
                this.writeError("character");
            } else {
                charValue = input.charAt(0);
                ok = true;
            }
        } while (!ok);
        return charValue;
    }

    public void writeln() {
        System.out.println();
    }

    public void write(String string) {
        System.out.print(string);
    }

    public void writeln(String string) {
        System.out.println(string);
    }

    public void write(char character) {
        System.out.print(character);
    }

    public void writeln(int integer) {
        System.out.println(integer);
    }

    private void writeError(String format) {
        System.out.println("FORMAT ERROR! " + "Enter a " + format + " formatted value.");
    }
}

控制台测试:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.io.BufferedReader;
import java.io.IOException;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;

public class ConsoleTest {

    @Mock
    private BufferedReader bufferedReader;
    @InjectMocks
    private Console console;

    @BeforeEach
    public void before(){
        initMocks(this);
        //this.console = new Console();
    }
    @Test
    public void givenConsoleWhenReadStringThenValue() throws IOException {
        String string = "yes";
        when(this.bufferedReader.readLine()).thenReturn(string);
        assertThat(this.console.readString("title"), is(string));
    }
}

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://maven.apache.org/POM/4.0.0"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <modules>

    </modules>

    <artifactId>solution.java.swing.socket.sql</artifactId>
    <groupId>usantatecla.tictactoe</groupId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>${project.groupId}.${project.artifactId}</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.6.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-inline</artifactId>
            <version>3.6.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <version>3.6.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest</artifactId>
            <version>2.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.3</version>
                <executions>
                    <execution>
                        <id>default-prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-report</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
                <dependencies>
                    <dependency>
                        <groupId>org.junit.platform</groupId>
                        <artifactId>junit-platform-surefire-provider</artifactId>
                        <version>1.2.0</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.22.2</version>
                <dependencies>
                    <dependency>
                        <groupId>org.junit.platform</groupId>
                        <artifactId>junit-platform-surefire-provider</artifactId>
                        <version>1.2.0</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

感谢和问候社区!

xmq68pz9

xmq68pz91#

我个人并不喜欢mockito,我更喜欢使用一个接口和两个实现(一个用于生产,一个用于测试)来完全控制我的类。
因此,这不会直接回答您关于mockito的问题,但它允许您完全控制代码的行为,而无需使用其他框架。
您可以定义一个非常简单的界面:

public interface Reader {
    String readLine();
}

然后,在类控制台中使用该接口:

public class Console {
    private final Reader reader;

    public Console(Reader reader) {
        this.reader = reader;
    }

    //Replace all your this.bufferedReader.readLine() by this.reader.readLine();

}

因此,在生产代码中,您可以使用缓冲读取器的实际实现:

public class ProductionReader implements Reader {

    private final BufferedReader bufferedReader = new BufferedReader(...);

    @Override
    public String readLine() {
        this.bufferedReader.readLine();
    }

}
Console console = new Console(new ProductionReader());

... 在测试中,您可以使用测试实现:

public class TestReader implements Reader {
    @Override
    public String readLine() {
        return "Yes";
    }
}
Console console = new Console(new TestReader());

请注意,在您的特定情况下,您可以使用mockito模拟行为,但在许多其他情况下,您将需要更复杂的方法,并且ove将允许您完全控制和完全调试代码,而无需添加任何依赖项。

相关问题