Migrate Couchbase tests to JUnit 5.

Closes #664
This commit is contained in:
Mark Paluch
2023-05-15 11:32:12 +02:00
parent 545d957031
commit ea17c12f93
10 changed files with 304 additions and 309 deletions

View File

@@ -17,94 +17,91 @@ package example.springdata.couchbase.repository;
import static org.assertj.core.api.Assertions.*;
import example.springdata.couchbase.model.Airline;
import example.springdata.couchbase.util.CouchbaseAvailableRule;
import java.util.List;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.couchbase.core.CouchbaseOperations;
import org.springframework.test.context.junit4.SpringRunner;
import example.springdata.couchbase.model.Airline;
import example.springdata.couchbase.util.EnabledOnCouchbaseAvailable;
/**
* Integration tests showing basic CRUD operations through {@link AirlineRepository}.
*
* @author Denis Rosa
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@EnabledOnCouchbaseAvailable
public class AirlineRepositoryIntegrationTests {
@ClassRule //
public static CouchbaseAvailableRule COUCHBASE = CouchbaseAvailableRule.onLocalhost();
@Autowired
AirlineRepository airlineRepository;
@Autowired AirlineRepository airlineRepository;
@Autowired
CouchbaseOperations couchbaseOperations;
@Autowired CouchbaseOperations couchbaseOperations;
@BeforeEach
public void before() {
if (couchbaseOperations.existsById().one("LH")) {
couchbaseOperations.removeById().one("LH");
}
}
@Before
public void before() {
if (couchbaseOperations.existsById().one("LH")) {
couchbaseOperations.removeById().one("LH");
}
}
/**
* The derived query executes a N1QL query emitting a single element.
*/
@Test
public void shouldFindAirlineN1ql() {
/**
* The derived query executes a N1QL query emitting a single element.
*/
@Test
public void shouldFindAirlineN1ql() {
List<Airline> airlines = airlineRepository.findByIata("TQ");
assertThat(airlines.get(0).getCallsign()).isEqualTo("TXW");
}
List<Airline> airlines = airlineRepository.findByIata("TQ");
assertThat(airlines.get(0).getCallsign()).isEqualTo("TXW");
}
/**
* The derived query executes a N1QL query and the emitted element is used to invoke
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(Object)} for an Id-based lookup.
* Queries without a result do not emit a value.
*/
@Test
public void shouldFindById() {
/**
* The derived query executes a N1QL query and the emitted element is used to invoke
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(Object)} for an Id-based
* lookup. Queries without a result do not emit a value.
*/
@Test
public void shouldFindById() {
Airline airline = airlineRepository.findByIata("TQ").get(0);
assertThat(airlineRepository.findById(airline.getId()).isPresent());
}
Airline airline = airlineRepository.findByIata("TQ").get(0);
assertThat(airlineRepository.findById(airline.getId()).isPresent());
}
/**
* Find all {@link Airline}s applying the {@code airlines/all} view.
*/
@Test
public void shouldFindByView() {
/**
* Find all {@link Airline}s applying the {@code airlines/all} view.
*/
@Test
public void shouldFindByView() {
List<Airline> airlines = airlineRepository.findAllBy();
List<Airline> airlines = airlineRepository.findAllBy();
assertThat(airlines).hasSizeGreaterThan(100);
}
assertThat(airlines).hasSizeGreaterThan(100);
}
/**
* Created elements are emitted by the
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#save(Object)} method.
*/
@Test
public void shouldCreateAirline() {
/**
* Created elements are emitted by the
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#save(Object)} method.
*/
@Test
public void shouldCreateAirline() {
Airline airline = new Airline();
Airline airline = new Airline();
airline.setId("LH");
airline.setIata("LH");
airline.setIcao("DLH");
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
airline.setId("LH");
airline.setIata("LH");
airline.setIcao("DLH");
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
airlineRepository.save(airline);
airlineRepository.save(airline);
assertThat(airlineRepository.findById("LH")).contains(airline);
}
assertThat(airlineRepository.findById("LH")).contains(airline);
}
}

View File

@@ -17,111 +17,108 @@ package example.springdata.couchbase.repository;
import static org.assertj.core.api.Assertions.*;
import example.springdata.couchbase.model.Airline;
import example.springdata.couchbase.util.CouchbaseAvailableRule;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.couchbase.core.CouchbaseOperations;
import org.springframework.test.context.junit4.SpringRunner;
import example.springdata.couchbase.model.Airline;
import example.springdata.couchbase.util.EnabledOnCouchbaseAvailable;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
/**
* Integration tests showing basic CRUD operations through {@link ReactiveAirlineRepository}
*
* @author Mark Paluch
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@EnabledOnCouchbaseAvailable
public class ReactiveAirlineRepositoryIntegrationTests {
@ClassRule //
public static CouchbaseAvailableRule COUCHBASE = CouchbaseAvailableRule.onLocalhost();
@Autowired
ReactiveAirlineRepository airlineRepository;
@Autowired ReactiveAirlineRepository airlineRepository;
@Autowired
CouchbaseOperations couchbaseOperations;
@Autowired CouchbaseOperations couchbaseOperations;
@BeforeEach
public void before() {
if (couchbaseOperations.existsById().one("LH")) {
couchbaseOperations.removeById().one("LH");
}
}
@Before
public void before() {
if (couchbaseOperations.existsById().one("LH")) {
couchbaseOperations.removeById().one("LH");
}
}
/**
* The derived query executes a N1QL query emitting a single element.
*/
@Test
public void shouldFindAirlineN1ql() {
/**
* The derived query executes a N1QL query emitting a single element.
*/
@Test
public void shouldFindAirlineN1ql() {
airlineRepository.findByIata("TQ") //
.as(StepVerifier::create) //
.assertNext(it -> {
assertThat(it.getCallsign()).isEqualTo("TXW");
}).verifyComplete();
}
airlineRepository.findByIata("TQ") //
.as(StepVerifier::create) //
.assertNext(it -> {
assertThat(it.getCallsign()).isEqualTo("TXW");
}).verifyComplete();
}
/**
* The derived query executes a N1QL query and the emitted element is used to invoke
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(Object)} for an Id-based lookup.
* Queries without a result do not emit a value.
*/
@Test
public void shouldFindById() {
/**
* The derived query executes a N1QL query and the emitted element is used to invoke
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(Object)} for an Id-based
* lookup. Queries without a result do not emit a value.
*/
@Test
public void shouldFindById() {
Mono<Airline> airline = airlineRepository.findByIata("TQ") //
.map(Airline::getId) //
.flatMap(airlineRepository::findById);
Mono<Airline> airline = airlineRepository.findByIata("TQ") //
.map(Airline::getId) //
.flatMap(airlineRepository::findById);
airline.as(StepVerifier::create) //
.assertNext(it -> {
airline.as(StepVerifier::create) //
.assertNext(it -> {
assertThat(it.getCallsign()).isEqualTo("TXW");
}).verifyComplete();
assertThat(it.getCallsign()).isEqualTo("TXW");
}).verifyComplete();
}
}
/**
* Find all {@link Airline}s applying the {@code airlines/all} view.
*/
@Test
public void shouldFindAll() {
airlineRepository.findAllBy().count() //
.as(StepVerifier::create) //
.assertNext(count -> {
/**
* Find all {@link Airline}s applying the {@code airlines/all} view.
*/
@Test
public void shouldFindAll() {
airlineRepository.findAllBy().count() //
.as(StepVerifier::create) //
.assertNext(count -> {
assertThat(count).isGreaterThan(100);
}).verifyComplete();
}
assertThat(count).isGreaterThan(100);
}).verifyComplete();
}
/**
* Created elements are emitted by the
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#save(Object)} method.
*/
@Test
public void shouldCreateAirline() {
/**
* Created elements are emitted by the
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#save(Object)} method.
*/
@Test
public void shouldCreateAirline() {
Airline airline = new Airline();
Airline airline = new Airline();
airline.setId("LH");
airline.setIata("LH");
airline.setIcao("DLH");
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
airline.setId("LH");
airline.setIata("LH");
airline.setIcao("DLH");
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
Mono<Airline> airlineMono = airlineRepository.save(airline) //
.map(Airline::getId) //
.flatMap(airlineRepository::findById);
Mono<Airline> airlineMono = airlineRepository.save(airline) //
.map(Airline::getId) //
.flatMap(airlineRepository::findById);
airlineMono.as(StepVerifier::create) //
.expectNext(airline) //
.verifyComplete();
}
airlineMono.as(StepVerifier::create) //
.expectNext(airline) //
.verifyComplete();
}
}

View File

@@ -17,21 +17,18 @@ package example.springdata.couchbase.template;
import static org.assertj.core.api.Assertions.*;
import example.springdata.couchbase.model.Airline;
import example.springdata.couchbase.util.CouchbaseAvailableRule;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.couchbase.core.CouchbaseOperations;
import org.springframework.data.couchbase.core.ReactiveCouchbaseOperations;
import org.springframework.test.context.junit4.SpringRunner;
import example.springdata.couchbase.model.Airline;
import example.springdata.couchbase.util.EnabledOnCouchbaseAvailable;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
/**
* Integration tests showing basic CRUD operations through
@@ -40,61 +37,57 @@ import org.springframework.test.context.junit4.SpringRunner;
* @author Mark Paluch
* @author Denis Rosa
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@EnabledOnCouchbaseAvailable
public class ReactiveJavaCouchbaseOperationsIntegrationTests {
@ClassRule //
public static CouchbaseAvailableRule COUCHBASE = CouchbaseAvailableRule.onLocalhost();
@Autowired
ReactiveCouchbaseOperations operations;
@Autowired
ReactiveCouchbaseOperations operations;
@Autowired
CouchbaseOperations couchbaseOperations;
@Autowired
CouchbaseOperations couchbaseOperations;
@BeforeEach
public void before() {
if (couchbaseOperations.existsById().one("LH")) {
couchbaseOperations.removeById().one("LH");
}
}
@Before
public void before() {
if (couchbaseOperations.existsById().one("LH")) {
couchbaseOperations.removeById().one("LH");
}
}
/**
* Find all {@link Airline}s applying the _class filter .
*/
@Test
public void shouldFindByAll() {
operations.findByQuery(Airline.class).all() //
.count() //
.as(StepVerifier::create) //
.assertNext(count -> {
/**
* Find all {@link Airline}s applying the _class filter .
*/
@Test
public void shouldFindByAll() {
operations.findByQuery(Airline.class).all() //
.count() //
.as(StepVerifier::create) //
.assertNext(count -> {
assertThat(count).isGreaterThan(100);
}) //
.verifyComplete();
}
assertThat(count).isGreaterThan(100);
}) //
.verifyComplete();
}
/**
* Created elements are emitted by {@link ReactiveCouchbaseOperations#upsertById(Class)} )}.
*/
@Test
public void shouldCreateAirline() {
Airline airline = new Airline();
/**
* Created elements are emitted by {@link ReactiveCouchbaseOperations#upsertById(Class)} )}.
*/
@Test
public void shouldCreateAirline() {
Airline airline = new Airline();
airline.setId("LH");
airline.setIata("LH");
airline.setIcao("DLH");
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
airline.setId("LH");
airline.setIata("LH");
airline.setIcao("DLH");
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
Mono<Airline> airlineMono = operations.upsertById(Airline.class).one(airline) //
.map(Airline::getId) //
.flatMap(id -> operations.findById(Airline.class).one(id));
Mono<Airline> airlineMono = operations.upsertById(Airline.class)
.one(airline) //
.map(Airline::getId) //
.flatMap(id -> operations.findById(Airline.class).one(id));
airlineMono.as(StepVerifier::create) //
.expectNext(airline).verifyComplete();
}
airlineMono.as(StepVerifier::create) //
.expectNext(airline).verifyComplete();
}
}

View File

@@ -22,12 +22,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
<build>

View File

@@ -17,28 +17,15 @@ package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.type.AnnotatedTypeMetadata;
import example.springdata.couchbase.util.CouchbaseAvailableRule;
/**
* @author Michael Reiche
*/
@SpringBootApplication
@Conditional(DemoApplication.CouchbaseAvailable.class)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
static class CouchbaseAvailable implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return CouchbaseAvailableRule.onLocalhost().isAvailable();
}
}
}

View File

@@ -15,25 +15,20 @@
*/
package com.example.demo;
import org.junit.ClassRule;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import example.springdata.couchbase.util.CouchbaseAvailableRule;
import example.springdata.couchbase.util.EnabledOnCouchbaseAvailable;
/**
* @author Michael Reiche
* @author Christoph Strobl
*/
@SpringBootTest
@ContextConfiguration(classes = DemoApplication.class)
@SpringBootTest(classes = DemoApplication.class)
@EnabledOnCouchbaseAvailable
class DemoApplicationTests {
@ClassRule //
public static CouchbaseAvailableRule COUCHBASE = CouchbaseAvailableRule.onLocalhost();
@Test
void contextLoads() {
}

View File

@@ -1,5 +1,6 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@@ -15,8 +16,9 @@
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@@ -1,82 +0,0 @@
/*
* Copyright 2017-2021 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
*
* https://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 example.springdata.couchbase.util;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import javax.net.SocketFactory;
import org.junit.AssumptionViolatedException;
import org.junit.rules.ExternalResource;
/**
* Rule to check Couchbase server availability. If Couchbase is not running, tests are skipped.
*
* @author Mark Paluch
*/
public class CouchbaseAvailableRule extends ExternalResource {
private final String host;
private final int port;
private final Duration timeout = Duration.ofSeconds(1);
private CouchbaseAvailableRule(String host, int port) {
this.host = host;
this.port = port;
}
/**
* Create a new rule requiring Couchbase running on {@code localhost} on {@code 8091}.
*
* @return the test rule.
*/
public static CouchbaseAvailableRule onLocalhost() {
return new CouchbaseAvailableRule("localhost", 8091);
}
@Override
protected void before() throws Throwable {
check((b, throwable) -> {
if (throwable != null) {
throw new AssumptionViolatedException(
String.format("Couchbase not available on on %s:%d. Skipping tests.", host, port), throwable);
}
});
}
public boolean isAvailable() {
AtomicBoolean b = new AtomicBoolean();
check((avail, t) -> b.set(avail));
return b.get();
}
private void check(BiConsumer<Boolean, Throwable> c) {
try (Socket socket = SocketFactory.getDefault().createSocket()) {
socket.connect(new InetSocketAddress(host, port), Math.toIntExact(timeout.toMillis()));
c.accept(true, null);
} catch (IOException e) {
c.accept(false, e);
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2020-2021 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
*
* https://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 example.springdata.couchbase.util;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* {@code @EnabledOnCouchbaseAvailable} is used to signal that the annotated test class or test method is only <em>enabled</em>
* if Couchbase is running.
* <p/>
* When applied at the class level, all test methods within that class will be enabled.
*
* @author Mark Paluch
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@ExtendWith(EnabledOnCouchbaseCondition.class)
public @interface EnabledOnCouchbaseAvailable {
/**
* Couchbase host.
*/
String host() default "localhost";
/**
* Couchbase port number.
*/
int port() default 8091;
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2020-2021 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
*
* https://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 example.springdata.couchbase.util;
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.*;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.platform.commons.util.AnnotationUtils;
/**
* {@link ExecutionCondition} for {@link EnabledOnCouchbaseCondition @EnabledOnCouchbaseAvailable}.
*
* @author Mark Paluch
* @see EnabledOnCouchbaseCondition
*/
class EnabledOnCouchbaseCondition implements ExecutionCondition {
private static final ConditionEvaluationResult ENABLED_BY_DEFAULT = enabled("@EnabledOnCouchbaseAvailable is not present");
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
var optional = AnnotationUtils.findAnnotation(context.getElement(), EnabledOnCouchbaseAvailable.class);
if (optional.isEmpty()) {
return ENABLED_BY_DEFAULT;
}
var annotation = optional.get();
try (var socket = new Socket()) {
socket.connect(new InetSocketAddress(annotation.host(), annotation.port()), 100);
return enabled(String.format("Connection successful to Couchbase at %s:%d", annotation.host(), annotation.port()));
} catch (IOException e) {
return disabled(
String.format("Cannot connect to Couchbase at %s:%d (%s)", annotation.host(), annotation.port(), e));
}
}
}