JUnit :: 或者如何喜欢 JavaRush 验证器
简要说明为什么我们需要这个野兽?JUnit是一个用于自动测试好代码或不太好代码的框架。你可以说: - 为什么我需要这个 swing,我可以轻松简单地测试我好的 Java 代码。你可以写很多介绍性的歌词,但我不是什么诗人,咱们言归正传吧……创建一个对象
因此,为了测试某些东西,我们首先需要一个测试对象。我们面前有一项任务。- 我们需要一个对象来存储有关用户的信息。
- Id - 必须按照添加新用户的顺序进行计数。
- 用户名。
- 他的年龄。
- 性别(男/女)
-
有必要提供用户列表的存储。
-
班级一定可以。
- 生成所有用户的列表。
- 按性别(男性/女性)生成用户列表。
- 返回总列表中用户的数量,并根据用户的性别计算数量。
- 按用户年龄计算总金额,并考虑性别。
- 计算总体平均年龄和按性别划分的平均年龄。
User
包含字段的 Java 类:
private int id;
private String name;
private int age;
private Sex sex;
这足以存储用户数据,让我们看看该任务还需要什么。我们需要以某种方式存储所有用户,让我们在类中创建一个静态字段allUsers
,我认为这样就可以了Map<Integer, User>
private static Map<Integer, User> allUsers;
我们还需要以某种方式为用户分配一个序列号,让我们创建一个静态计数器字段,在创建新用户时,该字段将Id
为该用户分配一个序列号。
private static int countId = 0;
所以,我们似乎已经整理好了字段,让我们为我们的对象编写一个构造函数,并为字段id
, name
, age
,编写 getter sex
。heterae 没什么复杂的,我们向IDEA寻求帮助吧,她永远不会拒绝,我们会让构造函数变得有点棘手。设计师一定能够做到。初始化字段,检查 中是否有这样的对象allUsers
,如果没有这样的对象,则增加我们的计数器countId++
并将其添加到所有用户的列表中。allUsers
如果该字段尚未初始化,则还要初始化该字段。为了方便搜索相同的对象,我们将重新定义方法,equals()
并且再次向我们心爱的IDEAhashCode()
寻求帮助并按字段进行比较,,。另外,让我们创建一个私有方法来检查这样的对象是否在列表中。 name
age
sex
hasUser()
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age &&
Objects.equals(name, user.name) &&
sex == user.sex;
}
@Override
public int hashCode() {
return Objects.hash(name, age, sex);
}
最后,我遇到了这样的设计师。
public User(String name, int age, Sex sex) {
if (allUsers == null){
allUsers = new HashMap<>();
}
this.name = name;
this.age = age;
this.sex = sex;
if (!hasUser()){
countId++;
this.id = countId;
allUsers.put(id, this);
}
}
和一个私有辅助方法
private boolean hasUser(){
for (User user : allUsers.values()){
if (user.equals(this) && user.hashCode() == this.hashCode()){
return true;
}
}
return false;
}
并且还重新定义toString()
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
现在是时候实现所需方法的逻辑了。由于逻辑主要使用静态字段,因此我们还将方法设为静态;对象不需要它们。
- 生成所有用户的列表。
- 按性别(男性/女性)生成用户列表。
-
返回总列表中用户的数量,并根据用户的性别计算数量。
public static int getHowManyUsers(){ return allUsers.size(); } public static int getHowManyUsers(Sex sex){ return getAllUsers(sex).size(); }
-
按用户年龄计算总金额,并考虑性别。让我们为此任务创建方法。
public static int getAllAgeUsers(){ int countAge = 0; for (User user : allUsers.values()){ countAge += user.age; } return countAge; } public static int getAllAgeUsers(Sex sex){ int countAge = 0; for (User user : getAllUsers(sex)){ countAge += user.age; } return countAge; }
-
计算总体平均年龄和按性别划分的平均年龄。
public static int getAverageAgeOfAllUsers(){ return getAllAgeUsers() / getHowManyUsers(); } public static int getAverageAgeOfAllUsers(Sex sex){ return getAllAgeUsers(sex) / getHowManyUsers(sex); }
太好了,我们已经描述了所需的对象及其行为。现在我们可以继续使用JUnit ,但首先我将向您展示如果我们在main中进行简单测试会是什么样子。
public static void main(String[] args) { new User("Eugene", 35, Sex.MALE); new User("Marina", 34, Sex.FEMALE); new User("Alina", 7, Sex.FEMALE); System.out.println("All users:"); User.getAllUsers().forEach(System.out::println); System.out.println("All users: MALE"); User.getAllUsers(Sex.MALE).forEach(System.out::println); System.out.println("All users: FEMALE"); User.getAllUsers(Sex.FEMALE).forEach(System.out::println); System.out.println("================================================"); System.out.println(" all users: " + User.getHowManyUsers()); System.out.println(" all MALE users: " + User.getHowManyUsers(Sex.MALE)); System.out.println("all FEMALE users: " + User.getHowManyUsers(Sex.FEMALE)); System.out.println("================================================"); System.out.println(" total age of all users: " + User.getAllAgeUsers()); System.out.println(" total age of all MALE users: " + User.getAllAgeUsers(Sex.MALE)); System.out.println("total age of all FEMALE users: " + User.getAllAgeUsers(Sex.FEMALE)); System.out.println("================================================"); System.out.println(" average age of all users: " + User.getAverageAgeOfAllUsers()); System.out.println(" average age of all MALE users: " + User.getAverageAgeOfAllUsers(Sex.MALE)); System.out.println("average age of all FEMALE users: " + User.getAverageAgeOfAllUsers(Sex.FEMALE)); System.out.println("================================================"); }
控制台的输出看起来像这样,然后我们将比较是否正常运行。当然,我们可以更深入地编写比较逻辑,并查看我们的计算结果,即使我们不确定我们是否能够提供所有内容。
//output Все пользователи: User{id=1, name='Eugene', age=35, sex=MALE} User{id=2, name='Marina', age=34, sex=FEMALE} User{id=3, name='Alina', age=7, sex=FEMALE} Все пользователи: MALE User{id=1, name='Eugene', age=35, sex=MALE} Все пользователи: FEMALE User{id=2, name='Marina', age=34, sex=FEMALE} User{id=3, name='Alina', age=7, sex=FEMALE} ================================================ всех пользователей: 3 всех пользователей MALE: 1 всех пользователей FEMALE: 2 ================================================ общий возраст всех пользователей: 76 общий возраст всех пользователей MALE: 35 общий возраст всех пользователей FEMALE: 41 ================================================ средний возраст всех пользователей: 25 средний возраст всех пользователей MALE: 35 средний возраст всех пользователей FEMALE: 20 ================================================ Process finished with exit code 0
我们对这个结果并不满意,在主要测试结束后,我们需要JUnit。
点a和bgetAllUsers()
可以通过返回 all 列表的方法和返回列表的User
重载方法来很好地处理,具体取决于传递的参数。getAllUsers(Sex sex)
Sex
public static List<User> getAllUsers(){
return new ArrayList<>(allUsers.values());
}
public static List<User> getAllUsers(Sex sex){
List<User> listAllUsers = new ArrayList<>();
for (User user : allUsers.values()){
if (user.sex == sex){
listAllUsers.add(user);
}
}
return listAllUsers;
}
如何将 JUnit 连接到项目
问题是如何将其连接到项目。对于那些了解情况的人来说,我不会选择Maven,因为这是一个完全不同的故事。;) 打开项目结构 Ctrl + Alt + Shift + S -> Libraries -> 点击 + (New Project Library) -> select from Maven, 然后我们看到这样一个窗口,在搜索栏中输入“junit:junit:4.12” ,等到找到->确定!-> 好的! 您应该得到这个结果 单击 OK,恭喜 JUnit 已添加到项目中。让我们继续。现在我们需要为 Java 类创建测试,将光标放在类的名称上User
-> 按 Alt + Enter -> 选择创建测试。我们应该看到一个窗口,在其中我们需要选择 JUnit4 库 -> 选择我们要测试的方法 -> OK 这个想法本身将创建一个类UserTest
,在这个类中我们将用测试覆盖我们的代码。让我们开始吧:
我们的第一个@Test
让我们创建第一个@Test方法getAllUsers()
- 这是一个应该返回所有用户的方法。测试将如下所示:
@Test
public void getAllUsers() {
// create test data
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
//create an expected list and fill it with the data of our method
List<User> expected = User.getAllUsers();
//create actual list put data in it for comparison
//what we expect the method to return
List<User> actual = new ArrayList<>();
actual.add(user);
actual.add(user1);
actual.add(user2);
//run the test if the list expected and actual are not equal
//the test will fail, read the test results in the console
Assert.assertEquals(expected, actual);
}
这里我们创建了几个测试用户 -> 创建一个列表expected
,我们将在其中放置其方法将返回给我们的用户getAllUsers()
-> 创建一个列表actual
,我们将在其中放置我们假设 Assert.assertEquals getAllUsers()
(actual, Expected) 方法的用户将被使用,我们将把检查过的和当前的列表传递给它。该方法将测试提供的列表中的对象并返回测试结果。该方法将比较对象的所有字段,如果存在继承,甚至会遍历父对象的字段。让我们运行第一个测试... 测试成功完成。现在让我们尝试让测试失败,为此我们需要更改其中一个测试列表,我们将通过注释掉向列表添加一个用户来实现此目的actual
。
@Test
public void getAllUsers() {
// create test data
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
//create an expected list and fill it with the data of our method
List<User> expected = User.getAllUsers();
//create actual list put data in it for comparison
//what we expect the method to return
List<User> actual = new ArrayList<>();
actual.add(user);
actual.add(user1);
//actual.add(user2);
//run the test if the list expected and actual are not equal
//the test will fail, read the test results in the console
Assert.assertEquals(expected, actual);
}
我们运行测试并看到以下内容: 现在我们可以看一下测试失败的原因。在这里我们看到检查列表中的用户比当前列表中的用户多。这就是失败的原因。我们可以在 main 中检查一下吗?JUnit : main = 1 : 0。让我们看看如果测试包含完全不同的对象,测试会是什么样子,让我们这样做:
@Test
public void getAllUsers() {
// create test data
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
//create an expected list and fill it with the data of our method
List<User> expected = User.getAllUsers();
//create actual list put data in it for comparison
//what we expect the method to return
List<User> actual = new ArrayList<>();
actual.add(new User("User1", 1, Sex.MALE));
actual.add(new User("User2", 2, Sex.FEMALE));
actual.add(new User("User3", 3, Sex.MALE));
//run the test if the list expected and actual are not equal
//the test will fail, read the test results in the console
Assert.assertEquals(expected, actual);
}
这就是控制台中的内容: 在这里您可以立即看到比较列表中有不同的用户,我们也可以单击&ltClick to see Difference>我们将得到一个窗口,在其中我们可以详细查看我们有哪些数据问题与. IDEA将突出显示所有存在差异的领域。 main
这会发生吗?- 不。getAllUsers()
JUnit : main = 2 : 0 好吧,让我们继续,我们还有一堆方法需要测试),但是等等,检查方法是否会返回给我们也不错,因为那是我们如何处理验证器捕获的JavaRushnull
任务)。就这样吧,三戈比的事……
@Test
public void getAllUsers_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers();
Assert.assertNotNull(expected);
}
是的,是的,验证器大致就是这样捕获我们的null
;)现在让我们运行这个测试,看看它向我们展示了什么。而且会显示错误,怎么办???这里怎么会出现测试错误))) 在这里我们可以收获用测试覆盖我们的代码的第一个成果。你还记得,allUsers
我们在构造函数中初始化了该字段,这意味着在调用该方法时getAllUsers()
,我们将引用一个尚未初始化的对象。让我们编辑它,从构造函数中删除初始化,并在声明字段时执行此操作。
private static Map<Integer, User> allUsers = new HashMap<>();
public User(String name, int age, Sex sex) {
this.name = name;
this.age = age;
this.sex = sex;
if (!hasUser()) {
countId++;
this.id = countId;
allUsers.put(id, this);
}
}
让我们运行测试,现在一切都很好。 我认为在 main 中捕获 NPE 并不容易,我想你会同意计数是 JUnit: main = 3: 0 然后我将用测试覆盖所有方法,让你看看它会是什么样子...现在我们的测试类如下所示:
package user;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class UserTest {
@Test
public void getAllUsers() {
// create test data
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
//create an expected list and fill it with the data of our method
List<User> expected = User.getAllUsers();
//create actual list put data in it for comparison
//what we expect the method to return
List<User> actual = new ArrayList<>();
actual.add(user);
actual.add(user1);
actual.add(user2);
//run the test if the list expected and actual are not equal
//the test will fail, read the test results in the console
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers();
Assert.assertNotNull(expected);
}
@Test
public void getAllUsers_MALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
List<User> expected = User.getAllUsers(Sex.MALE);
List<User> actual = new ArrayList<>();
actual.add(user);
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_MALE_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers(Sex.MALE);
Assert.assertNotNull(expected);
}
@Test
public void getAllUsers_FEMALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
List<User> expected = User.getAllUsers(Sex.FEMALE);
List<User> actual = new ArrayList<>();
actual.add(user1);
actual.add(user2);
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_FEMALE_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers(Sex.FEMALE);
Assert.assertNotNull(expected);
}
@Test
public void getHowManyUsers() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getHowManyUsers();
int actual = 3;
Assert.assertEquals(expected, actual);
}
@Test
public void getHowManyUsers_MALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getHowManyUsers(Sex.MALE);
int actual = 1;
Assert.assertEquals(expected, actual);
}
@Test
public void getHowManyUsers_FEMALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getHowManyUsers(Sex.FEMALE);
int actual = 2;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getAllAgeUsers();
int actual = 35 + 34 + 7;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers_MALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getAllAgeUsers(Sex.MALE);
int actual = 35;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers_FEMALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getAllAgeUsers(Sex.FEMALE);
int actual = 34 + 7;
Assert.assertEquals(expected, actual);
}
}
是的,事实证明它并不小,但是在处理大型项目时会发生什么。这里可以减少什么?在评估完所有内容之后,您可以看到我们在每个测试中创建了测试数据,并且这里注释可以帮助我们。我们假设 @Before
- 该注释@Before
表明该方法将在每个被测试的方法之前执行@Test
。这就是我们带有注释的测试类现在的样子@Before
:
package user;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class UserTest {
private User user;
private User user1;
private User user2;
@Before
public void setUp() throws Exception {
user = new User("Eugene", 35, Sex.MALE);
user1 = new User("Marina", 34, Sex.FEMALE);
user2 = new User("Alina", 7, Sex.FEMALE);
}
@Test
public void getAllUsers() {
List<User> expected = User.getAllUsers();
List<User> actual = new ArrayList<>();
actual.add(user);
actual.add(user1);
actual.add(user2);
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_NO_NULL() {
List<User> expected = User.getAllUsers();
Assert.assertNotNull(expected);
}
@Test
public void getAllUsers_MALE() {
List<User> expected = User.getAllUsers(Sex.MALE);
List<User> actual = new ArrayList<>();
actual.add(user);
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_MALE_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers(Sex.MALE);
Assert.assertNotNull(expected);
}
@Test
public void getAllUsers_FEMALE() {
List<User> expected = User.getAllUsers(Sex.FEMALE);
List<User> actual = new ArrayList<>();
actual.add(user1);
actual.add(user2);
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_FEMALE_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers(Sex.FEMALE);
Assert.assertNotNull(expected);
}
@Test
public void getHowManyUsers() {
int expected = User.getHowManyUsers();
int actual = 3;
Assert.assertEquals(expected, actual);
}
@Test
public void getHowManyUsers_MALE() {
int expected = User.getHowManyUsers(Sex.MALE);
int actual = 1;
Assert.assertEquals(expected, actual);
}
@Test
public void getHowManyUsers_FEMALE() {
int expected = User.getHowManyUsers(Sex.FEMALE);
int actual = 2;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers() {
int expected = User.getAllAgeUsers();
int actual = 35 + 34 + 7;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers_MALE() {
int expected = User.getAllAgeUsers(Sex.MALE);
int actual = 35;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers_FEMALE() {
int expected = User.getAllAgeUsers(Sex.FEMALE);
int actual = 34 + 7;
Assert.assertEquals(expected, actual);
}
}
好吧,你呢,它已经更有趣、更容易阅读了;)这是 JUnit 的注释列表,使用它们肯定更容易。
@Test – определяет что метод method() является тестовым.
@Before – указывает на то, что метод будет выполнятся перед каждым тестируемым методом @Test.
@After – указывает на то что метод будет выполнятся после каждого тестируемого метода @Test
@BeforeClass – указывает на то, что метод будет выполнятся в начале всех тестов,
а точней в момент запуска тестов(перед всеми тестами @Test).
@AfterClass – указывает на то, что метод будет выполнятся после всех тестов.
@Ignore – говорит, что метод будет проигнорирован в момент проведения тестирования.
(expected = Exception.class) – указывает на то, что в данном тестовом методе
вы преднамеренно ожидаете Exception.
(timeout = 100) – указывает, что тестируемый метод не должен занимать больше чем 100 миллисекунд.
用于检查的主要类方法Assert
:
fail(String) – указывает на то что бы тестовый метод завалился при этом выводя текстовое сообщение.
assertTrue([message], boolean condition) – проверяет, что логическое condition истинно.
assertsEquals([String message], expected, actual) – проверяет, что два значения совпадают.
Примечание: для массивов проверяются ссылки, а не содержание массивов.
assertNull([message], object) – проверяет, что an object является пустым null.
assertNotNull([message], object) – проверяет, что an object не является пустым null.
assertSame([String], expected, actual) – проверяет, что обе переменные относятся к одному an objectу.
assertNotSame([String], expected, actual) – проверяет, что обе переменные относятся к разным an objectм.
这就是我们如何在 Maven 中添加 JUnit 4.12 依赖项
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
此处继续 -> JUnit 第二部分
GO TO FULL VERSION