java - 如何在一组值上正确使用 assertThrows?
问题描述
我已经学习了一点Java,所以请告知在这种情况下异常抛出测试应该是什么样子?我有以下赌博机课程。然后对其进行 2 次测试。我真的不知道第二种方法(shouldThrowWhenNumbersOutOfRange)中的“整数”应该遵循什么。您能否告知确切的语法?
public class GamblingMachine {
public int howManyWins(Set<Integer> userNumbers) throws InvalidNumbersException {
validateNumbers(userNumbers);
Set<Integer> computerNumbers = generateComputerNumbers();
int count = 0;
for (Integer number : userNumbers) {
if (computerNumbers.contains(number)) {
count++;
}
}
return count;
}
private void validateNumbers(Set<Integer> numbers) throws InvalidNumbersException {
if (numbers.size() != 6) {
throw new InvalidNumbersException();
}
if (numbers.stream().anyMatch(number -> number < 1 || number > 49)) { //anyMatch-function to check whether any element in list satisfy given condition
throw new InvalidNumbersException();
}
}
private Set<Integer> generateComputerNumbers() {
Set<Integer> numbers = new HashSet<>();
Random generator = new Random();
while(numbers.size() < 6) {
numbers.add(generator.nextInt(49) + 1);
}
return numbers;
}
}
private GamblingMachine machine = new GamblingMachine();
@ParameterizedTest
@NullAndEmptySource
public void shouldThrowWhenNumbersEmpty(Set<Integer> numbers) throws InvalidNumbersException {
Assertions.assertThrows(NumberFormatException.class, () -> {
Integer.parseInt(" ");
});
}
@ParameterizedTest
@CsvFileSource(resources ="/numbersOutOfRange.cvs", numLinesToSkip = 1)
public void shouldThrowWhenNumbersOutOfRange(Set<Integer> numbers) throws InvalidNumbersException {
Assertions.assertThrows(NumberFormatException.class, () -> {
Integer. //how code should look like here?
});
}
解决方案
测试的重点是,你知道,测试一些东西。您的shouldThrowWhenNumbersEmpty
测试不会那样做(好吧,它测试会Integer.parseInt(" ")
抛出一些东西。它当然会。你......不必测试核心库)。
换句话说,您的赌博机测试需要从您的 GamblingMachine 类中调用一些东西。这个想法是测试 GamblingMachine。不去测试Integer.parseInt
。
这也是一个奇怪的测试:为什么在 blazes 中是shouldThrowWhenNumbersEmpty
参数化的?我假设该测试的重点是:“确保赌博机在传递一组空数字时按设计工作,特别是在设计中声明InvalidNumbersException
如果你这样做会抛出 an 的部分”。
这是通过以下方式完成的:
@Test
public void shouldThrowWhenNumbersEmpty() {
Assertions.assertThrows(InvalidNumbersException.class, () -> {
Set<Integer> empty = Set.of();
machine.howManyWins(empty);
});
}
参数化测试是一个相当奇特的概念。您的测试设置似乎陷入了一个陷阱:您似乎设置了重复您的赌博机类中已有的所有逻辑,然后将此逻辑应用于传入(参数化)数据,找出您的赌博机应该做,然后仔细检查它的工作。
这不是您应该编写测试的方式。测试侧重于特定结果。参数化测试是有意义的,但前提是您必须为任何给定输入做的事情大致相同。例如:
善用参数化测试
你有一个包含一堆行的 csv 文件,每行都有 6 个卷 + 正确答案。您的参数化测试将每一行视为相同:howManyWins
使用 6 卷作为输入调用,然后检查是否howManyWins
返回预期值。
参数化测试使用不当
您有一个 csv 文件,其中包含一堆行,每行有 6 个卷。您的参数化测试将计算出正确的掷骰结果,然后调用赌博机,并检查赌博机给出的答案是否与您计算的结果相同。
这很糟糕:您只是在重复代码。这也意味着您的测试代码本身所做的不仅仅是最基本的(它正在执行一堆业务逻辑),因此提出了一个问题:那么谁来测试您的测试呢?
您的两种测试方法似乎都不应该被参数化,除非 csv 也包含结果。
推荐阅读
- python - 从json python将纪元时间转换为标准日期时间?
- python - 如何在不复制选择查询结果的情况下使用带有线程的 MYSQL 选择查询?
- python - 使用条件处理我的数据帧 - python jupyter notebook
- java - 错误Tomcat服务器无法在eclipse中启动
- javascript - jQuery替换跨度包含带有单个逗号的逗号
- python - 在 C++ 中使用来自 OpenCV 矩阵的特征将图像旋转 90 度
- javascript - 如何附加 AJAX 回复
- php - PHP比较日期返回true
- java - WebSphere Liberty 中具有相同 JNDI 的多个数据源
- javascript - 如何编写显示和隐藏密码输入字段的代码