我有一个禁用的JTable,它提供了一个弹出菜单:
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
public class DisabledTableFrame extends JFrame {
public DisabledTableFrame() {
setSize(200, 100);
setTitle(getClass().getCanonicalName());
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JTable table = new JTable();
add(table);
table.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
mouseReleased(e);
}
@Override
public void mouseReleased(MouseEvent e) {
new PopupMenu();
}
});
table.setEnabled(false);
setVisible(true);
}
public static void main(String[] args) {
new DisabledTableFrame();
}
private class PopupMenu extends JPopupMenu {
public PopupMenu() {
JMenuItem menuItem = new JMenuItem("TEST");
add(menuItem); …Run Code Online (Sandbox Code Playgroud) 我必须处理一个没有测试的遗留应用程序。因此,在开始重构之前,我想确保一切都按原样运行。
现在想象一下以下情况:
public SomeObject doSomething(final OtherObject x, final String something) {
if(x == null) throw new RuntimeException("x may not be null!");
...
}
Run Code Online (Sandbox Code Playgroud)
现在我想测试该空检查,以确保它有效并且重构后我不会丢失它。
所以我这样做了
@Test(expected = RuntimeException.class)
public void ifOtherObjectIsNullExpectRuntimeException() {
myTestObject.doSomething(null, "testString");
}
Run Code Online (Sandbox Code Playgroud)
现在,这当然有效。
但我想传递一个随机字符串,而不是“testString”。
所以我尝试了:
@Test(expected = RuntimeException.class)
public void ifOtherObjectIsNullExpectRuntimeException() {
myTestObject.doSomething(null, Mockito.anyString());
}
Run Code Online (Sandbox Code Playgroud)
但这是不允许的。据我所知
org.mockito.exceptions.misusing.InvalidUseOfMatchersException: ...您不能在验证或存根之外使用参数匹配器
我确实理解这句话的含义,但我想知道我是否仍然可以在不参数化我的测试等的情况下做我想做的事情。我唯一可以使用的库是 Junit、AssertJ、Mockito 和 Powermock。
有任何想法吗?
我有一个 getter 返回带有通配符的列表:
import java.util.List;
public interface Foo {
List<? extends Bar> getList();
}
Run Code Online (Sandbox Code Playgroud)
哪里Bar有其他接口。
当我用 AssertJ 编写断言时,如下所示:
assertThat(foo.getList()).containsExactly(bar1, bar3);
Run Code Online (Sandbox Code Playgroud)
编辑:我的完整用法是链接 ausingElementComparator并提供 aComparator<Bar>来比较预期Bar实例。
Comparator<Bar> comparator = createBarComparator()
assertThat(foo.getList()).usingElementComparator(comparator).containsExactly(bar1, bar3);
Run Code Online (Sandbox Code Playgroud)
我收到此编译错误:
ListAssert 类型中的方法 containsExactly(capture#46-of ? extends Bar...) 不适用于参数 (Bar, Bar)
我的第一个解决方案是投射结果:
assertThat((List<Bar>)foo.getList()).containsExactly(bar1, bar3);
Run Code Online (Sandbox Code Playgroud)
然后我收到警告:
类型安全:从列表到列表的未经检查的转换
可以使用 删除警告@SuppressWarnings("unchecked"),但中间的强制转换仍然无法使断言真正具有可读性。
我的第二个解决方案是指示 ELEMENT 泛型参数的值:
Assertions.<Bar>assertThat(foo.getList()).containsExactly(bar1, bar3);
Run Code Online (Sandbox Code Playgroud)
好一点,但也不是那么好(不可能静态导入,行的开头不利于可读性)
我想我正在寻找assertThat列表的其他方法,其中类类型可以指定为第二个参数:
@CheckReturnValue
public static <ELEMENT> ListAssert<ELEMENT> assertThat(List<? extends ELEMENT> actual, Class<ELEMENT> c) {
return AssertionsForInterfaceTypes.assertThat(actual);
} …Run Code Online (Sandbox Code Playgroud) 使用Hamcrest,可以很容易地取消匹配器。例如,您可以编写这样的断言:
assertThat("The dog bites Tom", not(stringContainsInOrder(Arrays.asList("Tom", "dog"))));
Run Code Online (Sandbox Code Playgroud)
也就是说,使用org.hamcrest.core.IsNot,org.hamcrest.core.AnyOf匹配器很容易合并或取反断言。
AssertJ中有等效的东西吗?我知道可以合并/取反Condition。但是普通的断言方法呢?例如,如果您想测试字符串不是仅由数字组成,该怎么做,即取反以下断言:
assertThat("1234xxx5678").containsOnlyDigits();
Run Code Online (Sandbox Code Playgroud) 我想将双精度值与 AssertJ 进行比较。我不明白为什么我的测试失败。
@Test
public void testInterestToQuote() {
double result = BasicCalculator.accumulationFactorByYearsAndInterest(years, interest)
Assertions.assertThat(result).isCloseTo(expected, Assertions.offset(0.1d))
}
Run Code Online (Sandbox Code Playgroud)
例外是:
java.lang.AssertionError:
Expecting:
<7.256571590148141E-5>
to be close to:
<7.25>
by less than <0.1> but difference was <7.249927434284099>.
(a difference of exactly <0.1> being considered valid)
Run Code Online (Sandbox Code Playgroud)
为什么断言失败?
在使用 Swing 开发 Java 桌面应用程序时,我遇到了直接测试 UI 的需要,而不仅仅是通过单元测试测试底层控制器/模型类。
这个答案(关于“基于 Swing 的应用程序的最佳测试工具是什么?”)建议使用FEST,不幸的是,它已停止使用。然而,有一些项目是从 FEST 离开的地方继续进行的。特别是一个(在这个答案中提到)引起了我的注意,因为我之前在单元测试中使用过它:AssertJ。
显然有AssertJ Swing,它基于 FEST 并提供了一些编写 Swing UI 测试的易于使用的方法。但是,进行初始/工作设置仍然很麻烦,因为很难说从哪里开始。
如何为以下示例 UI 创建最小的测试设置(仅包含两个类)?
约束:Java SE、Swing UI、Maven 项目、JUnit
public class MainApp {
/**
* Run me, to use the app yourself.
*
* @param args ignored
*/
public static void main(String[] args) {
MainApp.showWindow().setSize(600, 600);
}
/**
* Internal standard method to initialize the view, returning the main JFrame (also to be …Run Code Online (Sandbox Code Playgroud) 我想测试一个特定的方法是否可以毫无例外地处理一堆字符串。因此,我想使用 AssertJ 的软断言,例如:
SoftAssertion softly = new SoftAssertion();
for (String s : strings) {
Foo foo = new Foo();
try {
foo.bar(s);
// Mark soft assertion passed.
} catch (IOException e) {
// Mark soft assertion failed.
}
}
softly.assertAll();
Run Code Online (Sandbox Code Playgroud)
不幸的是,我必须分别使用 AssertJ 1.x 和 Java 6,所以我无法利用这一点:
assertThatCode(() -> {
// code that should throw an exception
...
}).doesNotThrowAnyException();
Run Code Online (Sandbox Code Playgroud)
有没有办法用 AssertJ(或 JUnit)做到这一点?
我想测试两个对象的相等性,但对double它们的某些嵌套属性上存在的值的精度有一定的判断力。usingComparatorForTypeFoo似乎是一个合适的解决方案,但如果我的对象具有类型属性,Bar其中Bar.baz是double我希望应用此精度判断的属性,则它似乎不起作用。该示例isEqualToComparingFieldByFieldRecursively并不能完全解决我正在尝试测试的情况。
一些示例代码
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Comparator;
import java.util.Objects;
import org.junit.Test;
public class ComparatorForTypeTest {
private static final Comparator<Double> DOUBLE_COMPARATOR = new Comparator<Double>() {
@Override
public int compare(Double d1, Double d2) {
return Math.abs(d1 - d2) <= 0.1 ? 0 : 1;
}
};
class Foo {
private int id;
private double baz;
private Bar bar;
public Foo(int id, double baz, Bar bar) {
this.id = …Run Code Online (Sandbox Code Playgroud) 我想用一个assert声明一个对象的几个属性。
使用JUnit 4和Hamcrest,我将编写如下内容:
assertThat(product, allOf(
hasProperty("name", is("Coat")),
hasProperty("available", is(true)),
hasProperty("amount", is(12)),
hasProperty("price", is(new BigDecimal("88.0")))
));
Run Code Online (Sandbox Code Playgroud)
问:如何使用JUnit 5和AssertJ在一个断言调用中断言几个属性?或者,在JUnit 5 Universe中,这样做的最佳方法是什么。
注意:我当然可以创建具有所有所需属性的对象并执行
assertThat(actualProduct, is(expectedProduct))
Run Code Online (Sandbox Code Playgroud)
但这不是重点。
我使用 Assertj Swing(版本 3.17.0)进行的 GUI 单元测试都在本地通过,但有时在 CI 服务器中失败。如果我重试足够长的时间,最终测试套件会变成绿色。我很难弄清楚如何修复这些测试。
我使用 Java 8 和 Github Actions 作为 CI。正如类似问题中所建议的,我使用 VNC 在 CI 上无头运行这些测试,命令如下:
./execute-on-vnc.sh mvn -B -f pom.xml clean verify
Run Code Online (Sandbox Code Playgroud)
这是失败的测试示例(我正在模拟控制器,只是验证单击按钮实际上会使用正确的参数调用控制器方法):
@Mock private ItemController controller;
@Test @GUITest
public void testAddItemButtonShouldDelegateToControllerAddItem() {
window.textBox("itemIdTextField").enterText("1");
window.textBox("itemNameTextField").enterText("Some Item");
window.button(JButtonMatcher.withName("addItemButton")).click();
verify(controller).addItem(new Item("1", "Some Item"));
}
Run Code Online (Sandbox Code Playgroud)
下面是处理 JButton 上的点击的非常直接的代码:
addItemButton.addActionListener(e ->
controller.addItem(new Item(itemIdTextField.getText(), itemNameTextField.getText()))
);
Run Code Online (Sandbox Code Playgroud)
测试每次都在本地通过,没有任何问题,但在 CI 上经常失败,并出现以下错误:
testAddItemButtonShouldDelegateToControllerAddItem(com.example.view.swing.ItemSwingViewTest)
Time elapsed: 0.985 sec <<< FAILURE!
Wanted but not invoked:
controller.addItem(
Item{id='1', name='Some Item'}
);
Actually, there were …Run Code Online (Sandbox Code Playgroud)