[英]JUnit5: Forward every method call on object to wrapper function
我有以下情況:
我有一個 class 我想用 JUnit/Mockito 進行測試,但我想添加一些代碼,這些代碼應該在對 object 的每個方法調用中執行。
例如,如果對測試的 class 的調用花費超過特定時間量,我希望測試失敗(忽略與@Timeout
類似的功能已經存在,這只是一個簡單的示例)。 到目前為止,我所做的是編寫一個將方法/lambda 作為參數的方法,並做到這一點。 調用如下所示:
Object result = failOnTimeout( () -> testedInstance.calledMethod(x, y) );
這有一個缺點,我需要記住包裝每個方法調用。 有沒有更好的方法來規避這種情況? 我想要的理想行為是這樣的:
@BeforeAll
public void setup() {
testedInstace = new testedClass();
wrapMethodCall(testedInstance, failOnTimeout);
}
@Test
public void acualTest() {
Object result = testedInstance.calledMethod(x, y); //Implicitly calls 'failOnTimeout'
// ...
}
如果有人可以讓我知道是否存在此功能或可以解決我的問題的功能,將不勝感激。
在您的情況下,我看到了一些明顯的解決方案。 假設我們有這樣一個 class:
public class TestedClass {
public void calledMethod(int x, int y) {
System.out.println("Hello, Alexander");
}
}
首先,您可以使用 Mockito 方法。 並使用org.mockito.stubbing.Answer
class 和Mockito.spy(...)
方法。 例如:
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doAnswer;
public class TestedClassTestMockitoWay {
@Test
void calledMethodTest() {
TestedClass original = new TestedClass();
TestedClass spy = Mockito.spy(original);
Answer<Void> answer = new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocationOnMock) {
timeoutWrapper(() -> {
try {
invocationOnMock.callRealMethod();
} catch (Throwable ignore) {
}
});
return null;
}
private void timeoutWrapper(Runnable runnable) {
//todo: timeout implementation
System.out.println("before");
runnable.run();
System.out.println("after");
}
};
doAnswer(answer).when(spy).calledMethod(anyInt(), anyInt());
spy.calledMethod(1, 2);
}
}
第二個選項是經過測試的 class 的 inheritance。 如果您測試的 class 不是最終的,那么您可以繼承它。 例如:
import org.junit.jupiter.api.Test;
class TestedClassTestInheritanceWay {
@Test
void calledMethodTest() {
TimeoutTestedClass testedClass = new TimeoutTestedClass();
testedClass.calledMethod(1, 2);
}
private static class TimeoutTestedClass extends TestedClass {
@Override
public void calledMethod(int x, int y) {
timeoutWrapper(() -> super.calledMethod(x, y));
}
private void timeoutWrapper(Runnable runnable) {
//todo: timeout implementation
System.out.println("before");
runnable.run();
System.out.println("after");
}
}
}
或者,如果您測試的 class 是最終的。 你可以裝飾它們:
import org.junit.jupiter.api.Test;
public class TestedClassTestCompositionWay {
@Test
void calledMethodTest() {
TestedClass original = new TestedClass();
TimeoutTestedClass testedClass = new TimeoutTestedClass(original);
testedClass.calledMethod(1, 2);
}
private static class TimeoutTestedClass {
private final TestedClass testedClass;
private TimeoutTestedClass(TestedClass testedClass) {
this.testedClass = testedClass;
}
public void calledMethod(int x, int y) {
timeoutWrapper(() -> testedClass.calledMethod(x, y));
}
private void timeoutWrapper(Runnable runnable) {
//todo: timeout implementation
System.out.println("before");
runnable.run();
System.out.println("after");
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.