在很多时候,程序猿们更关注代码本身,而不愿意把时间花费在环境搭建上,这也是Docker变得越来越受欢迎的原因之一。test-containers是Docker生态圈中的一颗新星,其 主要针对测试领域、背靠Docker实现环境百宝箱功能

  test-containers: 你要的环境,我都有~

  假设我们现在需要一个redis-cluster环境来学习reids pipeline相关的代码知识,那么就需要搭建一套redis集群:

环境支持方式 直接搭建 docker搭建 使用test-container
工作量(简单预估) 100个单位 30个单位 15个单位

test-container环境支持(示例):

提示一 test-container基于Docker,使用test-container前需要安装Docker环境。

提示二 test-container提供的环境不能应用于生产、只能用于测试环境等场景。

使用test-container提供单机redis:

  • 环境基类

    import com.niantou.testcontainer.ExcludedAllAutoConfiguration;
    import com.niantou.testcontainer.author.JustryDeng;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Assert;
    import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
    import org.springframework.context.ApplicationContextInitializer;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.Import;
    import org.springframework.test.context.ContextConfiguration;
    import org.testcontainers.containers.GenericContainer;
    import org.testcontainers.junit.jupiter.Container;
    import org.testcontainers.junit.jupiter.Testcontainers;
    import org.testcontainers.utility.DockerImageName;/*** 单机redis环境支持** @author {@link JustryDeng}* @since 2020/11/13 16:14:18*/
    @Slf4j
    @Testcontainers
    @Import(value = {ExcludedAllAutoConfiguration.class, RedisAutoConfiguration.class})
    @ContextConfiguration(initializers = RedisStandaloneEnvSupport .Initializer.class)
    public class RedisStandaloneEnvSupport implements RedisEnvSupport {/** 标准的docker镜像(即${镜像名}:${tag名}) */private static final String DOCKER_IMAGE_NAME = "redis:5.0.3-alpine";/** docker开启的端口 */private static final int CONTAINER_PORT = 6379;@Containerpublic static GenericContainer<?> redisContainer = new GenericContainer<>(DockerImageName.parse(DOCKER_IMAGE_NAME)).withExposedPorts(CONTAINER_PORT);/*** init application context** @author {@link JustryDeng}* @since 2020/11/14 19:22:23*/public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(@SuppressWarnings("NullableProblems") ConfigurableApplicationContext configurableApplicationContext) {String redisIpAddress = redisContainer.getContainerIpAddress();log.info("redisIpAddress is [{}]", redisIpAddress);System.setProperty("spring.redis.host", redisIpAddress);Integer redisPort = redisContainer.getMappedPort(CONTAINER_PORT);log.info("redisPort is [{}]", redisPort);Assert.assertNotNull("redisPort is null", redisPort);System.setProperty("spring.redis.port", redisPort.toString());}}}
    
  • 测试类

    import com.niantou.testcontainer.author.JustryDeng;
    import com.niantou.testcontainer.redis.RedisStandaloneEnvSupport;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Assert;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.redis.core.StringRedisTemplate;import javax.annotation.Resource;
    import java.time.Duration;
    import java.util.concurrent.TimeUnit;/*** 测试** @author {@link JustryDeng}* @since 2020/11/13 16:36:21*/
    @Slf4j
    @SpringBootTest
    public class RedisStandaloneTest extends RedisStandaloneEnvSupport {@ResourceStringRedisTemplate stringRedisTemplate;@Testvoid one() throws InterruptedException {String name = stringRedisTemplate.opsForValue().get("name");System.err.println(name);Assert.assertNull(name);String justryDeng = "JustryDeng";stringRedisTemplate.opsForValue().set("name", justryDeng, Duration.ofSeconds(3));name = stringRedisTemplate.opsForValue().get("name");System.err.println(name);Assert.assertEquals(justryDeng, name);TimeUnit.SECONDS.sleep(3);name = stringRedisTemplate.opsForValue().get("name");System.err.println(name);Assert.assertNull(name);}}
    
  • 输出

使用test-container提供集群redis:

  • 环境基类

    import com.niantou.testcontainer.ExcludedAllAutoConfiguration;
    import com.niantou.testcontainer.author.JustryDeng;
    import com.niantou.testcontainer.redis.helper.ClientResources4Test;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
    import org.springframework.context.ApplicationContextInitializer;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.Import;
    import org.springframework.test.context.ContextConfiguration;
    import org.testcontainers.containers.FixedHostPortGenericContainer;
    import org.testcontainers.containers.GenericContainer;
    import org.testcontainers.junit.jupiter.Container;
    import org.testcontainers.junit.jupiter.Testcontainers;/*** redis集群环境支持** @author {@link JustryDeng}* @since 2020/11/13 16:14:18*/
    @Slf4j
    @Testcontainers
    @Import(value = {ExcludedAllAutoConfiguration.class, ClientResources4Test.class, RedisAutoConfiguration.class})
    @ContextConfiguration(initializers = RedisClusterEnvSupport.Initializer.class)
    public class RedisClusterEnvSupport implements RedisEnvSupport {/** 标准的docker镜像(即${镜像名}:${tag名}) */private static final String DOCKER_IMAGE_NAME = "grokzen/redis-cluster:6.0.7";/*** 集群最好用FixedHostPortGenericContainer, 主动避免端口冲突即可*/@Container@SuppressWarnings("deprecation")public static GenericContainer<?> redisContainer = new FixedHostPortGenericContainer<>(DOCKER_IMAGE_NAME).withFixedExposedPort(7000, 7000).withFixedExposedPort(7001, 7001).withFixedExposedPort(7002, 7002).withFixedExposedPort(7003, 7003).withFixedExposedPort(7004, 7004).withFixedExposedPort(7005, 7005);/*** init application context** @author {@link JustryDeng}* @since 2020/11/14 19:22:23*/public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(@SuppressWarnings("NullableProblems") ConfigurableApplicationContext configurableApplicationContext) {String redisIpAddress = redisContainer.getContainerIpAddress();String nodesInfo = redisIpAddress + ":" + 7000+ "," + redisIpAddress + ":" + 7001+ "," + redisIpAddress + ":" + 7002+ "," + redisIpAddress + ":" + 7003+ "," + redisIpAddress + ":" + 7004+ "," + redisIpAddress + ":" + 7005;log.info("spring.redis.cluster.nodes is [{}]", nodesInfo);System.setProperty("spring.redis.cluster.nodes", nodesInfo);}}
    }
    
  • 测试类

    import com.niantou.testcontainer.author.JustryDeng;
    import com.niantou.testcontainer.redis.RedisClusterEnvSupport;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Assert;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.redis.core.StringRedisTemplate;import javax.annotation.Resource;
    import java.time.Duration;
    import java.util.concurrent.TimeUnit;/*** 测试** @author {@link JustryDeng}* @since 2020/11/13 16:36:21*/
    @Slf4j
    @SpringBootTest
    public class RedisClusterTest extends RedisClusterEnvSupport {@ResourceStringRedisTemplate stringRedisTemplate;@Testvoid one() throws InterruptedException {String name = stringRedisTemplate.opsForValue().get("name");System.err.println(name);Assert.assertNull(name);String justryDeng = "JustryDeng";stringRedisTemplate.opsForValue().set("name", justryDeng, Duration.ofSeconds(3));name = stringRedisTemplate.opsForValue().get("name");System.err.println(name);Assert.assertEquals(justryDeng, name);TimeUnit.SECONDS.sleep(3);name = stringRedisTemplate.opsForValue().get("name");System.err.println(name);Assert.assertNull(name);}}
    
  • 输出

使用test-container提供MySQL:

  • 环境基类

    import com.niantou.testcontainer.ExcludedAllAutoConfiguration;
    import com.niantou.testcontainer.author.JustryDeng;
    import com.zaxxer.hikari.HikariDataSource;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.ClassRule;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.context.ApplicationContextInitializer;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.Import;
    import org.springframework.test.context.ContextConfiguration;
    import org.testcontainers.containers.MySQLContainer;
    import org.testcontainers.utility.DockerImageName;/*** Mysql8环境支持** @author {@link JustryDeng}* @since 2020/11/17 14:14:43*/
    @Slf4j
    @ContextConfiguration(initializers = Mysql8EnvSupport.Initializer.class)
    @Import(value = {ExcludedAllAutoConfiguration.class, DataSourceAutoConfiguration.class})
    public class Mysql8EnvSupport implements MysqlEnvSupport{/** 标准的docker镜像(即${镜像名}:${tag名}) */private static final String DOCKER_IMAGE_NAME = "mysql:8.0.22";/** 数据库 */
    private static final String DATABASE = "mine_database";/** 连接池类型 */
    private static final Class<?> POOL_TYPE_CLASS = HikariDataSource.class;@ClassRule
    public static MySQLContainer<?> mySqlContainer = new MySQLContainer<>(DockerImageName.parse(DOCKER_IMAGE_NAME)).withDatabaseName(DATABASE)// 初始化脚本.withInitScript("mysql/init_mysql.sql")/// 配置文件///.withConfigurationOverride("mysql/config");/*** init application context** @author {@link JustryDeng}* @since 2020/11/14 19:22:23*/
    public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(@SuppressWarnings("NullableProblems") ConfigurableApplicationContext configurableApplicationContext) {// startmySqlContainer.start();String jdbcUrl = mySqlContainer.getJdbcUrl();int endIndex = jdbcUrl.indexOf("?");String additionalSetting = "?characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false";if (endIndex < 0) {jdbcUrl = jdbcUrl + additionalSetting;} else {jdbcUrl = jdbcUrl.substring(0, endIndex) + additionalSetting;}System.setProperty("spring.datasource.url", jdbcUrl);System.setProperty("spring.datasource.username", mySqlContainer.getUsername());System.setProperty("spring.datasource.password", mySqlContainer.getPassword());System.setProperty("spring.datasource.driver-class-name", mySqlContainer.getDriverClassName());System.setProperty("spring.datasource.type", POOL_TYPE_CLASS.getName());}
    }}
    
  • 基类中涉及到的脚本的位置及内容为

  • 测试类

    import com.niantou.testcontainer.author.JustryDeng;
    import com.niantou.testcontainer.mysql.Mysql8EnvSupport;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Select;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;import javax.annotation.Resource;
    import java.util.List;
    import java.util.Map;/*** 测试** @author {@link JustryDeng}* @since 2020/11/13 16:36:21*/
    @Slf4j
    @SpringBootTest
    public class Mysql8Test extends Mysql8EnvSupport {@ResourceTestMapper testMapper;@Testvoid one() {System.err.println(testMapper.count());List<Map<String, Object>> x = testMapper.selectAll();System.err.println(x);}@Mapperpublic interface TestMapper {@Select("select count(*) from employee")int count();@Select("select * from employee")List<Map<String, Object>> selectAll();}}
    
  • 输出

使用test-container提供pgSQL:

  • 环境基类

    import com.niantou.testcontainer.ExcludedAllAutoConfiguration;
    import com.niantou.testcontainer.author.JustryDeng;
    import com.zaxxer.hikari.HikariDataSource;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.ClassRule;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.context.ApplicationContextInitializer;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.Import;
    import org.springframework.test.context.ContextConfiguration;
    import org.testcontainers.containers.PostgreSQLContainer;
    import org.testcontainers.utility.DockerImageName;/*** PostgreSql10环境支持** @author {@link JustryDeng}* @since 2020/11/17 21:14:29*/
    @Slf4j
    @ContextConfiguration(initializers = PostgreSql10EnvSupport.Initializer.class)
    @Import(value = {ExcludedAllAutoConfiguration.class, DataSourceAutoConfiguration.class})
    public class PostgreSql10EnvSupport implements PostgreSqlEnvSupport {/** 标准的docker镜像(即${镜像名}:${tag名}) */private static final String DOCKER_IMAGE_NAME = "postgres:10.15";/** 数据库 */private static final String DATABASE = "mine_database";/** 连接池类型 */private static final Class<?> POOL_TYPE_CLASS = HikariDataSource.class;@ClassRulepublic static PostgreSQLContainer<?> pgSqlContainer = new PostgreSQLContainer<>(DockerImageName.parse(DOCKER_IMAGE_NAME)).withDatabaseName(DATABASE)// 初始化脚本.withInitScript("postgresql/init_postgresql.sql");/*** init application context** @author {@link JustryDeng}* @since 2020/11/14 19:22:23*/public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(@SuppressWarnings("NullableProblems") ConfigurableApplicationContext configurableApplicationContext) {// startpgSqlContainer.start();System.setProperty("spring.datasource.url", pgSqlContainer.getJdbcUrl());System.setProperty("spring.datasource.username", pgSqlContainer.getUsername());System.setProperty("spring.datasource.password", pgSqlContainer.getPassword());System.setProperty("spring.datasource.driver-class-name", pgSqlContainer.getDriverClassName());System.setProperty("spring.datasource.type", POOL_TYPE_CLASS.getName());}}}
    
  • 基类中涉及到的脚本的位置及内容为

  • 测试类

    import com.niantou.testcontainer.author.JustryDeng;
    import com.niantou.testcontainer.postgresql.PostgreSql10EnvSupport;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Select;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;import javax.annotation.Resource;
    import java.util.List;
    import java.util.Map;/*** 测试** @author {@link JustryDeng}* @since 2020/11/13 16:36:21*/
    @Slf4j
    @SpringBootTest
    public class PostgreSql10Test extends PostgreSql10EnvSupport {@ResourceTestMapper testMapper;@Testvoid one() {System.err.println(testMapper.count());System.err.println(testMapper.selectAll());}@Mapperpublic interface TestMapper {@Select("select count(*) from employee")int count();@Select("select * from employee")List<Map<String, Object>> selectAll();}}
    
  • 输出

使用test-container提供Kafka:

  • 环境基类

    import com.niantou.testcontainer.ExcludedAllAutoConfiguration;
    import com.niantou.testcontainer.author.JustryDeng;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.ClassRule;
    import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration;
    import org.springframework.context.ApplicationContextInitializer;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.Import;
    import org.springframework.kafka.annotation.EnableKafka;
    import org.springframework.test.context.ContextConfiguration;
    import org.testcontainers.containers.KafkaContainer;
    import org.testcontainers.utility.DockerImageName;/*** 一个简单的kafka环境支持** @author {@link JustryDeng}* @since 2020/11/18 12:11:54*/
    @Slf4j
    @EnableKafka
    @ContextConfiguration(initializers = KafkaSimpleEnvSupport.Initializer.class)
    @Import(value = {ExcludedAllAutoConfiguration.class, KafkaAutoConfiguration.class})
    public class KafkaSimpleEnvSupport implements KafkaEnvSupport {/** 标准的docker镜像(即${镜像名}:${tag名}) */private static final String DOCKER_IMAGE_NAME = "confluentinc/cp-kafka:5.4.3";@ClassRulepublic static KafkaContainer kafkaContainer = new KafkaContainer(DockerImageName.parse(DOCKER_IMAGE_NAME));/*** init application context** @author {@link JustryDeng}* @since 2020/11/14 19:22:23*/public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(@SuppressWarnings("NullableProblems") ConfigurableApplicationContext configurableApplicationContext) {// startkafkaContainer.start();String bootstrapServers = kafkaContainer.getBootstrapServers();System.setProperty("spring.kafka.bootstrap-servers", bootstrapServers);// 因为是测试环境, 这里用earliest, 以避免在没有提交offset情况下,用latest不会读取旧数据的问题System.setProperty("spring.kafka.consumer.auto-offset-reset", "earliest");}}
    }
    
  • 测试类

    import com.niantou.testcontainer.author.JustryDeng;
    import com.niantou.testcontainer.kafka.KafkaSimpleEnvSupport;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Assert;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.context.annotation.Import;
    import org.springframework.kafka.annotation.KafkaListener;
    import org.springframework.kafka.core.KafkaTemplate;import javax.annotation.Resource;
    import java.util.UUID;
    import java.util.concurrent.TimeUnit;/*** 测试** @author {@link JustryDeng}* @since 2020/11/18 12:15:47*/
    @Slf4j
    @SpringBootTest
    @Import(value = {KafkaSimpleTest.MyConsumer.class, KafkaSimpleTest.MyProducer.class})
    public class KafkaSimpleTest extends KafkaSimpleEnvSupport {static final String TOPIC_NAME4TEST = "my-topic4test";@ResourceMyProducer myProducer;@Testvoid one() throws InterruptedException {// 生产消息for (int i = 0; i < 10; i++) {myProducer.sendMessage("邓沙利文-" + i);}// sleep几秒,以便观察消费者是否消费消息TimeUnit.SECONDS.sleep(3);Assert.assertTrue("消费消息失败(或消费消息超时)", MyConsumer.hasConsumedMsg);}/*** 生产者*/@Slf4jpublic static class MyProducer {@Resourceprivate KafkaTemplate<String, String> kafkaTemplate;public void sendMessage(String message) {kafkaTemplate.send(TOPIC_NAME4TEST, "key-" + UUID.randomUUID().toString(), message);}}/*** 消费者*/@SuppressWarnings("unused")@Slf4jpublic static class MyConsumer {/** 是否已经消费了消息 */static boolean hasConsumedMsg = false;@KafkaListener(topics = TOPIC_NAME4TEST, groupId = "group-b")public void consumerOne(String message) {log.info("consumerOne消费了消息 [{}]", message);hasConsumedMsg = true;}}
    }
    
  • 输出

使用test-container提供RabbitMQ:

  • 环境基类

    import com.niantou.testcontainer.ExcludedAllAutoConfiguration;
    import com.niantou.testcontainer.author.JustryDeng;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.ClassRule;
    import org.springframework.context.ApplicationContextInitializer;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.Import;
    import org.springframework.test.context.ContextConfiguration;
    import org.testcontainers.containers.RabbitMQContainer;/*** 一个简单的RabbitMQ环境支持** @author {@link JustryDeng}* @since 2020/11/20 12:49:45*/
    @Slf4j
    @ContextConfiguration(initializers = RabbitMqSimpleEnvSupport.Initializer.class)
    @Import(value = {ExcludedAllAutoConfiguration.class})
    public class RabbitMqSimpleEnvSupport {/** 标准的docker镜像(即${镜像名}:${tag名}) */private static final String DOCKER_IMAGE_NAME = "rabbitmq:management-alpine";@ClassRulepublic static RabbitMQContainer rabbitMqContainer = new RabbitMQContainer(DOCKER_IMAGE_NAME).withAdminPassword("ds123");/*** init application context** @author {@link JustryDeng}* @since 2020/11/14 19:22:23*/public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(@SuppressWarnings("NullableProblems") ConfigurableApplicationContext configurableApplicationContext) {// startrabbitMqContainer.start();String host = rabbitMqContainer.getHost();log.info("spring.rabbitmq.host={}", host);System.setProperty("spring.rabbitmq.host", host);Integer amqpPort = rabbitMqContainer.getAmqpPort();log.info("spring.rabbitmq.port={}", amqpPort);System.setProperty("spring.rabbitmq.port", String.valueOf(amqpPort));String adminUsername = rabbitMqContainer.getAdminUsername();log.info("spring.rabbitmq.username={}", adminUsername);System.setProperty("spring.rabbitmq.username", adminUsername);String adminPassword = rabbitMqContainer.getAdminPassword();log.info("spring.rabbitmq.password={}", adminPassword);System.setProperty("spring.rabbitmq.password", adminPassword);}}}
    
  • 测试类

    import com.niantou.testcontainer.author.JustryDeng;
    import com.niantou.testcontainer.rabbitmq.RabbitMqSimpleEnvSupport;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Assert;
    import org.junit.jupiter.api.Test;
    import org.springframework.amqp.core.AmqpTemplate;
    import org.springframework.amqp.core.Binding;
    import org.springframework.amqp.core.BindingBuilder;
    import org.springframework.amqp.core.DirectExchange;
    import org.springframework.amqp.core.Queue;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Import;import javax.annotation.Resource;
    import java.util.concurrent.TimeUnit;import static com.niantou.testcontainer.rabbitmq.test.RabbitMqSimpleTest.MyConfig.MY_EXCHANGE_NAME;
    import static com.niantou.testcontainer.rabbitmq.test.RabbitMqSimpleTest.MyConfig.QUEUE_NAME;
    import static com.niantou.testcontainer.rabbitmq.test.RabbitMqSimpleTest.MyConfig.ROUTING_KEY;/*** 测试** @author {@link JustryDeng}* @since 2020/11/18 12:15:47*/
    @Slf4j
    @SpringBootTest
    @Import(value = {RabbitMqSimpleTest.MyConsumer.class, RabbitMqSimpleTest.MyProducer.class,RabbitMqSimpleTest.MyConfig.class})
    public class RabbitMqSimpleTest extends RabbitMqSimpleEnvSupport {@ResourceMyProducer myProducer;@Testvoid one() throws InterruptedException {// 生产消息for (int i = 0; i < 10; i++) {myProducer.sendMessage("邓沙利文-" + i);}// sleep几秒,以便观察消费者是否消费消息TimeUnit.SECONDS.sleep(3);Assert.assertTrue("消费消息失败(或消费消息超时)", MyConsumer.hasConsumedMsg);}/*** 配置类*/@Slf4jpublic static class MyConfig {static final String ROUTING_KEY = "myRoutingKey";static final String QUEUE_NAME = "my-queue";static final String MY_EXCHANGE_NAME = "my-direct-exchange";@Beanpublic Queue myQueue() {return new Queue(QUEUE_NAME);}@Beanpublic DirectExchange myDirectExchange() {return new DirectExchange(MY_EXCHANGE_NAME);}@Beanpublic Binding myBinding(Queue myQueue, DirectExchange myDirectExchange) {return BindingBuilder.bind(myQueue).to(myDirectExchange).with(ROUTING_KEY);}}/*** 生产者*/@Slf4jpublic static class MyProducer {@Resourceprivate AmqpTemplate amqpTemplate;public void sendMessage(String message) {amqpTemplate.convertAndSend(MY_EXCHANGE_NAME, ROUTING_KEY, message);}}/*** 消费者*/@Slf4jpublic static class MyConsumer {/** 是否已经消费了消息 */static boolean hasConsumedMsg = false;@SuppressWarnings("unused")@RabbitListener(queues = QUEUE_NAME)public void consumerOne(String message) {log.info("consumerOne消费了消息 [{}]", message);hasConsumedMsg = true;}}
    }
    
  • 输出


test-containers,初步学习完毕!

^_^ 如有不当之处,欢迎指正

^_^ 参考链接
         https://www.testcontainers.org/

^_^ 测试代码托管链接
         https://github.com/JustryDeng…test-containers

^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng

基于docker的test-containers环境百宝箱相关推荐

  1. 基于Docker的深度学习环境NVIDIA和CUDA部署以及WSL和linux镜像问题

    基于Docker的深度学习环境部署 1. 什么是Docker? 2. 深度学习环境的基本要求 3. Docker的基本操作 3.1 在Windows上安装Docker 3.2 在Ubuntu上安装Do ...

  2. mac启动本地redis_通过 Laravel Sail 构建基于 Docker 的本地开发环境

    Laravel 官方最近发布了 Laravel Sail -- 一个轻量级的.基于 Docker 的 Laravel 本地集成开发环境,今天学院君就以 Mac 系统为例,给大家演示下如何基于 Lara ...

  3. docker容器管理 php,基于Docker的PHP开发环境

    [编者的话]本文作者是Geoffrey,他是一个PHP的Web开发者,喜欢DevOps和Docker.本文主要介绍了如何使用Docker构建PHP的开发环境,文中作者也探讨了构建基于Docker的开发 ...

  4. ubuntu18.04中基于Docker搭建tensorflow-gpu开发环境

    前提条件就不多提啦,首先得装好nvidia驱动和Docker19以上版本,网上有很多教程. 尝试1:拉取现有的deepo镜像制作 deepo是一个囊括几乎所有深度学习框架的开源镜像,这里我们选择拉取一 ...

  5. 基于Docker的Python开发

    作者|GUEST 编译|VK 来源|Analytics Vidhya 在PyCharm和Visual Studio代码上支持CUDA 介绍 如果你没有经验,建立一个开发环境是不容易的,特别是如果你想学 ...

  6. DNMP:基于docker搭建集成LNMP(nginx+mysql+php)

    有一天,主机商跑路了.迫于无奈之下,我需要进行数据迁移.原先用的主机我可以什么都不管,直接用就行.而现在,只有一个centos服务器.一切从零开始... 我曾试过一个一个安装,从docker入手,一步 ...

  7. 基于docker的 Hyperledger Fabric 多机环境搭建(上)

    环境:ubuntu 16.04 Docker  17.04.0-ce go 1.7.4 consoul v0.8.0.4 ======================================= ...

  8. 基于docker在Ubuntu上搭建TensorFlow-GPU计算环境

    这里转载一篇Docker安装TF GPU的版本 基于docker在Ubuntu上搭建TensorFlow-GPU计算环境 由于实验室的服务器有多人共享使用,而不同人的代码对应的keras和tensor ...

  9. Docker入门指南:基于 docker 搭建机器学习/深度学习开发环境

    实际工作中,许多项目开发需要在Linux服务器上进行,本文为习惯使用 Windows 操作系统的朋友介绍一种基于Docker的,跨平台.便携性(方便移植.重新部署.可远程访问)的开发环境搭建方法. 1 ...

  10. 【K8S】基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持续集成交付环境(环境搭建篇)

    写在前面 最近在 K8S 1.18.2 版本的集群上搭建DevOps环境,期间遇到了各种坑.目前,搭建环境的过程中出现的各种坑均已被填平,特此记录,并分享给大家! 服务器规划 IP 主机名 节点 操作 ...

最新文章

  1. H5用户地址位置选择地点获取经纬度(效果图)
  2. WPF学习拾遗(二)TextBlock换行
  3. 本科4篇顶会!清华特奖高天宇干货分享:我是这样写论文、做实验、与导师相处...
  4. 2dx解析cocosbuilder中使用layer时的缺陷
  5. linux运维实战练习-2015年9月13日-9月15日课程作业(练习)安排
  6. 下面代码打印的结果?
  7. Product Archive相关的标准function module
  8. html版本操作手册,全新HTML5用户手册(版本2017)–互联网股票买卖操作.PDF
  9. TODA-MES电池行业解决方案
  10. Java实现下载url视频资源
  11. 被反爬虫搞到心态崩溃
  12. Mac 安装非信任开发者软件
  13. unity 彩带粒子_unity游戏缤纷五彩纸屑粒子特效Confetti FX 1.0
  14. [译] 改善 DaVinci Resolve 性能的 5 个秘诀
  15. thinkpad x250装黑苹果教程_ThinkPad E450c 傻瓜式黑苹果一键安装教程
  16. Elasticsearch常见报错和处理方法
  17. java bigdecimal 开方_JAVA BigDecimal使用牛顿迭代法计算平方根(开方)
  18. 访客模式 无痕模式 区别_旧访客设计模式的新生活
  19. HTML5 drag和drop的亲手实践
  20. android照片美颜项目_照片美颜p图编辑app下载

热门文章

  1. python实验报告代写_Python 读写CSV作业代写代做、代写Python I/O文件读写程序作业、代写代做python 实验报告...
  2. jQuery插件库常用前端库引用地址详细提供
  3. java spi 热插拔_利用SPI机制实现责任链模式中的处理类热插拔
  4. 《孙子兵法》的优秀读后感作文2100字
  5. 【AI创新者】云知声梁家恩:当 AI 遇见 IoT——云知声的 AI 之路
  6. Python发送电子邮件.
  7. 面试HR常问的几个问题?
  8. python 操作word页眉表格_Python 如何对word文档(.docx)的页眉和页脚进行编辑?
  9. java做一个查询网页版_用java写一个网页输入url点击查询即可在下面显示网页源代码...
  10. Android关于BottomNavigationView效果实现指南