diff --git a/.gitignore b/.gitignore
index bbe265e1..25d57609 100755
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
target
+.idea/
*.iws
*.ipr
*.iml
diff --git a/awaitility-groovy/pom.xml b/awaitility-groovy/pom.xml
index 0a75dc2b..da7547a3 100755
--- a/awaitility-groovy/pom.xml
+++ b/awaitility-groovy/pom.xml
@@ -75,15 +75,6 @@
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 2.5.1
-
- 1.5
- 1.5
-
-
diff --git a/awaitility-java8/pom.xml b/awaitility-java8/pom.xml
new file mode 100644
index 00000000..4a93fa8f
--- /dev/null
+++ b/awaitility-java8/pom.xml
@@ -0,0 +1,64 @@
+
+
+ 4.0.0
+
+ awaitility-parent
+ com.jayway.awaitility
+ 1.5.1-SNAPSHOT
+
+ awaitility-java8
+ Awaitility support for Java 8
+ Simplifies Awaitility usage with Java 8
+ jar
+
+
+
+
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+
+
+
+ maven-install-plugin
+ 2.5.1
+
+
+ true
+
+
+
+
+
+
+
+ com.jayway.awaitility
+ awaitility
+ ${project.version}
+ test
+
+
+ com.jayway.awaitility
+ awaitility
+ ${project.version}
+ test-jar
+ test
+
+
+ org.assertj
+ assertj-core
+ 1.6.0
+ test
+
+
+ junit
+ junit
+ 4.10
+ test
+
+
+
+
diff --git a/awaitility-java8/src/main/java/.gitkeep b/awaitility-java8/src/main/java/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/awaitility-java8/src/test/java/com/jayway/awaitility/AwaitilityJava8Test.java b/awaitility-java8/src/test/java/com/jayway/awaitility/AwaitilityJava8Test.java
new file mode 100644
index 00000000..b1aac3f8
--- /dev/null
+++ b/awaitility-java8/src/test/java/com/jayway/awaitility/AwaitilityJava8Test.java
@@ -0,0 +1,82 @@
+package com.jayway.awaitility;
+
+import com.jayway.awaitility.classes.Asynch;
+import com.jayway.awaitility.classes.FakeRepository;
+import com.jayway.awaitility.classes.FakeRepositoryImpl;
+import com.jayway.awaitility.core.ConditionTimeoutException;
+import org.assertj.core.api.Assertions;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static com.jayway.awaitility.Awaitility.with;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for await().until(Runnable) using AssertionCondition.
+ *
+ * @author Marcin Zajączkowski, 2014-03-28
+ */
+public class AwaitilityJava8Test {
+
+ private FakeRepository fakeRepository;
+
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ @Before
+ public void setup() {
+ fakeRepository = new FakeRepositoryImpl();
+ Awaitility.reset();
+ }
+
+ @Test(timeout = 2000)
+ public void awaitAssertJAssertionAsLambda() {
+ new Asynch(fakeRepository).perform();
+ await().untilPass(() -> Assertions.assertThat(fakeRepository.getValue()).isEqualTo(1));
+ }
+
+ @SuppressWarnings("Convert2Lambda")
+ @Test(timeout = 2000)
+ public void awaitAssertJAssertionAsAnonymousClass() {
+ new Asynch(fakeRepository).perform();
+ await().untilPass(new Runnable() {
+ @Override
+ public void run() {
+ Assertions.assertThat(fakeRepository.getValue()).isEqualTo(1);
+ }
+ });
+ }
+
+ @Test(timeout = 2000)
+ public void awaitAssertJAssertionDisplaysOriginalErrorMessageAndTimeoutWhenConditionTimeoutExceptionOccurs() {
+ exception.expect(ConditionTimeoutException.class);
+ exception.expectMessage(startsWith(AwaitilityJava8Test.class.getName()));
+ exception.expectMessage(endsWith("expected:<[1]> but was:<[0]> within 120 milliseconds."));
+
+ new Asynch(fakeRepository).perform();
+ with().pollInterval(10, MILLISECONDS).then().await().atMost(120, MILLISECONDS).untilPass(
+ () -> Assertions.assertThat(fakeRepository.getValue()).isEqualTo(1));
+ }
+
+ @Test(timeout = 2000)
+ public void awaitJUnitAssertionAsLambda() {
+ new Asynch(fakeRepository).perform();
+ await().untilPass(() -> assertEquals(1, fakeRepository.getValue()));
+ }
+
+ @Test(timeout = 2000)
+ public void awaitJUnitAssertionDisplaysOriginalErrorMessageAndTimeoutWhenConditionTimeoutExceptionOccurs() {
+ exception.expect(ConditionTimeoutException.class);
+ exception.expectMessage(startsWith(AwaitilityJava8Test.class.getName()));
+ exception.expectMessage(endsWith("expected:<1> but was:<0> within 120 milliseconds."));
+
+ with().pollInterval(10, MILLISECONDS).then().await().atMost(120, MILLISECONDS).untilPass(
+ () -> assertEquals(1, fakeRepository.getValue()));
+ }
+}
diff --git a/awaitility-scala/pom.xml b/awaitility-scala/pom.xml
index 98854530..fa8d1d12 100755
--- a/awaitility-scala/pom.xml
+++ b/awaitility-scala/pom.xml
@@ -26,7 +26,7 @@
com.jayway.awaitility
awaitility
- ${version}
+ ${project.version}
@@ -37,6 +37,7 @@
org.scala-tools
maven-scala-plugin
+ 2.15.2
@@ -55,6 +56,7 @@
org.apache.maven.plugins
maven-eclipse-plugin
+ 2.9
true
diff --git a/awaitility/pom.xml b/awaitility/pom.xml
index 6e3ebf74..d4644a91 100755
--- a/awaitility/pom.xml
+++ b/awaitility/pom.xml
@@ -5,7 +5,6 @@
awaitility-parent
1.5.1-SNAPSHOT
- com.jayway.awaitility
awaitility
jar
http://github.com/jayway/awaitility
@@ -16,14 +15,16 @@
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
- 1.5
- 1.5
-
-
+
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+
diff --git a/awaitility/src/main/java/com/jayway/awaitility/core/AssertionCondition.java b/awaitility/src/main/java/com/jayway/awaitility/core/AssertionCondition.java
new file mode 100644
index 00000000..536aed90
--- /dev/null
+++ b/awaitility/src/main/java/com/jayway/awaitility/core/AssertionCondition.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jayway.awaitility.core;
+
+import java.util.concurrent.Callable;
+
+/**
+ * Condition implementation which takes an executable assertion which should throw {@link AssertionError} on assertion failure.
+ *
+ * @since 1.6.0
+ *
+ * @author Marcin Zajączkowski, 2014-03-28
+ */
+public class AssertionCondition implements Condition {
+
+ private final ConditionAwaiter conditionAwaiter;
+
+ private String lastExceptionMessage;
+
+ public AssertionCondition(final Runnable supplier, ConditionSettings settings) {
+ if (supplier == null) {
+ throw new IllegalArgumentException("You must specify a supplier (was null).");
+ }
+ Callable callable = new Callable() {
+ public Boolean call() throws Exception {
+ try {
+ supplier.run();
+ return true;
+ } catch (AssertionError e) {
+ lastExceptionMessage = e.getMessage();
+ return false;
+ }
+ }
+ };
+ conditionAwaiter = new ConditionAwaiter(callable, settings) {
+ @Override
+ protected String getTimeoutMessage() {
+ return supplier.getClass().getName() + " " + lastExceptionMessage;
+ }
+ };
+ }
+
+ public Void await() {
+ conditionAwaiter.await();
+ return null;
+ }
+}
diff --git a/awaitility/src/main/java/com/jayway/awaitility/core/ConditionFactory.java b/awaitility/src/main/java/com/jayway/awaitility/core/ConditionFactory.java
index db365a66..6ac2a429 100755
--- a/awaitility/src/main/java/com/jayway/awaitility/core/ConditionFactory.java
+++ b/awaitility/src/main/java/com/jayway/awaitility/core/ConditionFactory.java
@@ -377,6 +377,44 @@ public T until(final Callable supplier, final Matcher super T> matcher)
return until(new CallableHamcrestCondition(supplier, matcher, generateConditionSettings()));
}
+ /**
+ * Await until a {@link Runnable} supplier execution passes (ends without throwing an exception). E.g. with Java 8:
+ *
+ *
+ * await().untilPass(() -> Assertions.assertThat(personRepository.size()).isEqualTo(6));
+ *
+ * or
+ *
+ * await().untilPass(() -> assertEquals(6, personRepository.size()));
+ *
+ *
+ * This method is intended to benefit from lambda expressions introduced in Java 8. It allows to use standard AssertJ/FEST Assert assertions
+ * (by the way also standard JUnit/TestNG assertions) to test asynchronous calls and systems.
+ *
+ * {@link AssertionError} instances thrown by the supplier are treated as an assertion failure and proper error message is propagated on timeout.
+ * Other exceptions are rethrown immediately as an execution errors.
+ *
+ * Why technically it is completely valid to use plain Runnable class in Java 7 code, the resulting expression is very verbose and can decrease
+ * the readability of the test case, e.g.
+ *
+ *
+ * await().untilPass(new Runnable() {
+ * @Override
+ * public void run() {
+ * Assertions.assertThat(personRepository.size()).isEqualTo(6);
+ * }
+ * });
+ *
+ *
+ * @param supplier the supplier that is responsible for executing the assertion and throwing AssertionError on failure.
+ * @throws ConditionTimeoutException If condition was not fulfilled within the given time period.
+ *
+ * @since 1.6.0
+ */
+ public void untilPass(final Runnable supplier) {
+ until(new AssertionCondition(supplier, generateConditionSettings()));
+ }
+
/**
* Await until a Atomic variable has a value matching the specified
* {@link Matcher}. E.g.
diff --git a/pom.xml b/pom.xml
index 71cb01e9..dfbe6c5a 100755
--- a/pom.xml
+++ b/pom.xml
@@ -59,6 +59,7 @@
maven-release-plugin
+ 2.5
true
false
@@ -70,7 +71,26 @@
forked-path
+
+ maven-compiler-plugin
+
+
+
+
+ maven-compiler-plugin
+ 3.1
+
+ 1.5
+ 1.5
+
+
+
+ maven-jar-plugin
+ 2.4
+
+
+
@@ -80,6 +100,7 @@
maven-gpg-plugin
+ 1.5
false
@@ -97,12 +118,14 @@
true
maven-deploy-plugin
+ 2.8.1
true
maven-source-plugin
+ 2.2.1
attach-sources
@@ -148,5 +171,6 @@
awaitility
awaitility-scala
awaitility-groovy
+ awaitility-java8