#java #unit-testing #junit #jqwik
#java #модульное тестирование #junit #jqwik
Вопрос:
Проблема с тестированием
Я написал следующий пример кода и запустил его в IntelliJ и продолжал получать то же исключение в версии v1.5.0 . Тот же код отлично работает на 1.4.0 и ниже…
Это пример кода, до которого я сократил свой фактический тестовый код:
import java.util.Random;
import net.jqwik.api.Arbitraries;
import net.jqwik.api.Arbitrary;
import net.jqwik.api.Combinators;
public class Test {
public static Arbitrary<String> testing() {
return Combinators.withBuilder(StringBuilder::new)
.use(Arbitraries.of("123")).in(StringBuilder::append)
.build(StringBuilder::toString);
}
@org.junit.jupiter.api.Test
public void test() {
testing().generator(0).next(new Random()).value();
}
}
Отслеживание стека:
net.jqwik.engine.execution.lifecycle.OutsideJqwikException: The current action must be run on a jqwik thread, i.e. container, property or hook.
Maybe you spawned off a thread?
at net.jqwik.engine.execution.lifecycle.CurrentTestDescriptor.get(CurrentTestDescriptor.java:50)
at net.jqwik.engine.facades.StoreFacadeImpl.get(StoreFacadeImpl.java:24)
at net.jqwik.api.lifecycle.Store.get(Store.java:92)
at net.jqwik.api.lifecycle.Store.getOrCreate(Store.java:68)
at net.jqwik.engine.facades.Memoize.generatorStore(Memoize.java:13)
at net.jqwik.engine.facades.Memoize.memoizedGenerator(Memoize.java:26)
at net.jqwik.engine.facades.ArbitraryFacadeImpl.memoizedGenerator(ArbitraryFacadeImpl.java:221)
at net.jqwik.api.Arbitrary.generator(Arbitrary.java:92)
at net.jqwik.api.Combinators$Combinator2$1.rawGenerator(Combinators.java:264)
at net.jqwik.api.Combinators$Combinator2$1.generator(Combinators.java:255)
at net.jqwik.engine.facades.ArbitraryFacadeImpl$2.generator(ArbitraryFacadeImpl.java:79)
at com.test.my.code.project.Test.test(Test.java:18)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:129)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:129)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:189)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Process finished with exit code 255
- Удаление
.use(Arbitraries.of("123")).in(StringBuilder::append)
приведет к прохождению теста, поэтому исключение поступает из generate(int). - Изменение на .example или пометка с помощью @Example, похоже, также помогает, но я не думаю, что мне нужно это делать, учитывая, что это новая проблема после обновления.
Комментарии:
1. Я также отключил параллельное тестирование junit, поэтому тесты выполняются в основном потоке (хотя с 1.4.0 это не было проблемой) и по-прежнему выдает ту же ошибку.
Ответ №1:
Использование генераторов в том виде, в котором вы это делаете, больше не поддерживается jqwik. Вместо этого вы должны использовать: Arbitrary.sample()
or Arbitrary.sampleStream()
для генерации значений вне методов @Property
or @Example
:
@org.junit.jupiter.api.Test
public void test() {
testing().sample();
}
Причина в том, что для эффективной генерации значений требуется довольно много механизмов состояния под капотом.
Вы должны прочитать https://jqwik.net/docs/current/user-guide.html#using-arbitraries-directly и особенно https://jqwik.net/docs/current/user-guide.html#using-arbitraries-outside-jqwik-lifecycle для получения дополнительных указаний.
Кроме того, используйте по крайней мере версию 1.5.6 jqwik или, что еще лучше, самую последнюю версию 1.6.1.
Еще один вопрос, который приходит на ум: почему вы хотите самостоятельно генерировать образцы, а не использовать жизненный цикл jqwik? Для этого есть несколько веских причин, но стандартные варианты использования уже охвачены @Example
и @Property
.
Комментарии:
1. Спасибо, я попробовал образец, но на самом деле он не позволяет мне указывать динамическое начальное значение на основе теста. Например, я вычисляю начальное значение, например, long seed = 1294253% data.length(); , как я могу сделать выборку на основе этого начального значения?
2. Смотрите обсуждение в github.com/jlink/jqwik/issues/266