我只想测试是否使用google-truth抛出了给定消息的异常。
使用@Test(expected=
使用junit很容易做到这一点,但是我无法弄清楚如何用真相做到这一点。 ThrowableSubject周围没有样本。
我应该坚持使用普通JUnit
进行这类测试吗?
答案 0 :(得分:12)
[更新]
真理作者建议使用JUnit 4.13 / 5的assertThrows()
机制,因为这并不需要真理中的支持。这看起来更像是:
SpecificException e =
assertThrows(SpecificException.class, () -> doSomethingThatThrows());
assertThat(e).hasMessageThat().contains("blah blah blah");
assertThat(e).hasCauseThat().isInstanceOf(IllegalStateException.class);
assertThat(e).hasCauseThat().hasMessageThat().contains("blah");
建议使用try / fail / catch,因为它更简洁,避免"丢失失败"问题,并返回一个可以使用真值中的ThrowableSubject
断言的对象。
如果你没有assertThrows()
,那么请使用try / fail / catch模式,因为这是清楚明确的。
try {
doSomethingThatThrows();
fail("method should throw");
} catch (SpecificException e) {
// ensure that e was thrown from the right code-path
// especially important if it's something as frequent
// as an IllegalArgumentException, etc.
assertThat(e).hasMessage("blah blah blah");
}
虽然JUnit中存在@Rule ExpectedException
和@Test(exception=...)
,但Truth团队并不推荐这些,只要它们有一些微妙(并且不那么微妙)的方法,您可以编写通过但是哪个应该失败。
虽然尝试/失败/捕获也是如此,但内部Google通过使用error-prone来缓解此问题,http://www.webservicex.net/stockquote.asmx提供静态编译时检查以确保此模式不会忽略失败()等。强烈建议您使用容易出错或其他静态分析检查来捕获这些。遗憾的是,基于规则和注释的方法并不像这个try / catch块那样容易进行静态分析。
答案 1 :(得分:3)
作为此处的更新,我们已经摆脱了Christian所描述的模式,并且Issue #219已经关闭以支持JUnit的expectThrows()
(进入4.13,类似的方法已经存在在TestNG's Assert
)。
与expectThrows()
同时,您可以使用Truth制作assertions about the thrown exception。所以克里斯蒂安的榜样现在是:
SpecificException expected = expectThrows(
SpecificException.class, () -> doSomethingThatThrows());
assertThat(expected).hasMessageThat().contains("blah blah blah");
答案 2 :(得分:2)
目前没有以Exception
验证预期google-truth
的内置方式。您可以执行以下操作之一:
expected=
try...catch
围绕练习/行动/部分测试的方式,如@ c0der所提到的,which is what the unit tests for guava
do 我认为google-truth
没有任何类似的功能,因为它supports Java 1.6。
import com.google.common.truth.FailureStrategy;
import com.google.common.truth.Subject;
import com.google.common.truth.SubjectFactory;
import org.junit.Test;
import java.util.concurrent.Callable;
import static com.google.common.truth.Truth.assertAbout;
public class MathTest {
@Test
public void addExact_throws_ArithmeticException_upon_overflow() {
assertAbout(callable("addExact"))
.that(() -> Math.addExact(Integer.MAX_VALUE, 1))
.willThrow(ArithmeticException.class);
}
static <T> SubjectFactory<CallableSubject<T>, Callable<T>> callable(String displaySubject) {
return new SubjectFactory<CallableSubject<T>, Callable<T>>() {
@Override public CallableSubject<T> getSubject(FailureStrategy fs, Callable<T> that) {
return new CallableSubject<>(fs, that, displaySubject);
}
};
}
static class CallableSubject<T> extends Subject<CallableSubject<T>, Callable<T>> {
private final String displaySubject;
CallableSubject(FailureStrategy failureStrategy, Callable<T> callable, String displaySubject) {
super(failureStrategy, callable);
this.displaySubject = displaySubject;
}
@Override protected String getDisplaySubject() {
return displaySubject;
}
void willThrow(Class<?> clazz) {
try {
getSubject().call();
fail("throws a", clazz.getName());
} catch (Exception e) {
if (!clazz.isInstance(e)) {
failWithBadResults("throws a", clazz.getName(), "throws a", e.getClass().getName());
}
}
}
}
}