概述


对事务机制进行测试。

测试实例


测试实例 结果预测
发送正常 3条消息入队
发送异常 0条消息入队
接收正常 3条消息出队
接收异常 0条消息出队

demo设计


设计图

测试分工

测试类 测试方法
TransactedProducer.java
- 测试发送
sendNormal():void
- 测试“发送正常”
sendIntentional():void
- 测试“发送异常”
TransactedConsumer.java
- 测试接收
receiveNormal():void
- 测试“接收正常”
receiveIntentional():void
- 测试“接收异常”

测试步骤和结果


1.测试发送

1.1.测试发送正常

测试步骤
  1. 在ActiveMQ管理页面,删除example.queue
    - 如果存在就删除
  2. 运行TransactedProducer#sendNormal()
    - 发送消息到example.queue
  3. 查看ActiveMQ管理页面
    - example.queue中有3条消息入队
测试结果
符合预期。

1.2.测试发送异常

测试步骤
  1. 在ActiveMQ管理页面,删除example.queue
    - 如果存在就删除
  2. 运行TransactedProducer#sendIntentional()
    - 发送消息到example.queue
  3. 查看控制台和ActiveMQ管理页面
    - 控制台有异常抛出
    - example.queue中入队消息0
测试结果
符合预期。

2.测试接收

2.1.测试接收正常

测试步骤
  1. 在ActiveMQ管理页面,删除example.queue
    - 如果存在就删除
  2. 运行TransactedProducer#sendNormal()
    - 发送消息到example.queue
  3. 查看ActiveMQ管理页面
    - example.queue中有3条消息入队
  4. 运行TransactedConsumer#receiveNormal()
    - 从example.queue中接收消息
  5. 查看控制台和ActiveMQ管理页面
    - 控制台打印出3条信息
    - 管理页面看到example.queue中的3条消息出队
测试结果
符合预期。

2.2.测试接收异常

测试步骤
  1. 在ActiveMQ管理页面,删除example.queue
    - 如果存在就删除
  2. 运行TransactedProducer#sendNormal()
    - 发送消息到example.queue
  3. 查看ActiveMQ管理页面
    - example.queue中有3条消息入队
  4. 运行TransactedConsumer#receiveIntentional()
    - 从example.queue中接收消息
  5. 查看控制台和ActiveMQ管理页面
    - 控制台打印出3条消息和异常信息
    - 管理页面看到example.queue中出队消息0条
测试结果
符合预期。

代码


文件目录结构

jms-producer
|---- src/main/resources/
|---- jndi.properties
|---- src/main/java/
|---- cn.sinobest.asj.producer.jms.transaction
|---- TransactedProducer.java # 测试发送
jms-consumer
|---- src/main/resources/
|---- jndi.properties # 和jms-producer中的jndi.properties一致
|---- src/main/java/
|---- cn.sinobest.asj.consumer.jms.transaction
|---- TransactedConsumer.java # 测试接收

文件内容

1.jndi.propertie

 java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory

 # use the following property to configure the default connector
java.naming.provider.url=tcp://localhost:61616 # register some queues in JNDI using the form
# queue.[jndiName] = [physicalName]
queue.exampleQueue=example.queue # register some topics in JNDI using the form
# topic.[jndiName] = [physicalName]
topic.exampleTopic=example.topic

2.TransactedProducer.java

 package cn.sinobest.asj.producer.jms.transaction;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.junit.Test;
/**
* 事务的生产者.<br>
* 测试发送正常和发送异常.
* @author lijinlong
*
*/
public class TransactedProducer {
/** JNDI name for ConnectionFactory */
static final String CONNECTION_FACTORY_JNDI_NAME = "ConnectionFactory";
/** JNDI name for Queue Destination (use for PTP Mode) */
static final String QUEUE_JNDI_NAME = "exampleQueue"; /** 是否故意异常 */
boolean intentional = false; /**
* 测试发送正常.
*/
@Test
public void sendNormal() {
this.intentional = false;
send(QUEUE_JNDI_NAME);
} /**
* 测试发送异常.
*/
@Test
public void sendIntentional() {
this.intentional = true;
send(QUEUE_JNDI_NAME);
} /**
* 是否故意抛出异常.<br>
* 如果不抛出异常,会有3条消息入队;否则没有消息入队.
* @return
*/
private boolean isIntentional() {
return intentional;
} /**
* 发送到指定的目的地.
*
* @param destJndiName
* 目的地的JNDI name.
*/
private void send(String destJndiName) {
Context jndiContext = null;
ConnectionFactory connectionFactory = null;
Connection connection = null;
Session session = null;
Destination destination = null;
MessageProducer producer = null;
// create a JNDI API IntialContext object
try {
jndiContext = new InitialContext();
} catch (NamingException e) {
System.out.println("Could not create JNDI Context:"
+ e.getMessage());
System.exit(1);
}
// look up ConnectionFactory and Destination
try {
connectionFactory = (ConnectionFactory) jndiContext
.lookup(CONNECTION_FACTORY_JNDI_NAME);
destination = (Destination) jndiContext.lookup(destJndiName);
} catch (NamingException e) {
System.out.println("JNDI look up failed:" + e.getMessage());
System.exit(1);
}
// send Messages and finally release the resources.
try {
connection = connectionFactory.createConnection();
session = connection.createSession(Boolean.TRUE,
Session.SESSION_TRANSACTED);
producer = session.createProducer(destination); TextMessage message = session.createTextMessage();
for (int i = 0; i < 3; i++) {
message.setText(String.format("This is the %dth message.",
i + 1));
producer.send(message);
} if (isIntentional()) {
throw new JMSException("这是一个故意抛出的异常。");
} session.commit(); // 在最后提交
} catch (JMSException e) {
try {
session.rollback();
} catch (JMSException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
try {
if (session != null)
session.close();
if (connection != null)
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}

TransactedProducer.java

3.TransactedConsumer.java

 package cn.sinobest.asj.consumer.jms.transaction;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.junit.Test;
/**
* 事务的接收者.<br>
* 测试接收正常和接收异常.
* @author lijinlong
*
*/
public class TransactedConsumer {
/** JNDI name for ConnectionFactory */
static final String CONNECTION_FACTORY_JNDI_NAME = "ConnectionFactory";
/** JNDI name for Queue Destination (use for PTP Mode) */
static final String QUEUE_JNDI_NAME = "exampleQueue"; /** 是否故意异常 */
boolean intentional = false; @Test
public void receiveNormal() {
intentional = false;
receive(QUEUE_JNDI_NAME);
} @Test
public void receiveIntentional() {
intentional = true;
receive(QUEUE_JNDI_NAME);
} /**
* 是否故意抛出异常,以检查消息的出队情况.
* @return
*/
private boolean isIntentional() {
return intentional;
} /**
* 接收消息.<br>
*
* @param destJndiName
* 目的地的JNDI name.
*/
private void receive(String destJndiName) {
Context jndiContext = null;
ConnectionFactory connectionFactory = null;
Connection connection = null;
Session session = null;
Destination destination = null;
MessageConsumer consumer = null;
// create a JNDI API IntialContext object
try {
jndiContext = new InitialContext();
} catch (NamingException e) {
System.out.println("Could not create JNDI Context:"
+ e.getMessage());
System.exit(1);
}
// look up ConnectionFactory and Destination
try {
connectionFactory = (ConnectionFactory) jndiContext
.lookup(CONNECTION_FACTORY_JNDI_NAME);
destination = (Destination) jndiContext.lookup(destJndiName);
} catch (NamingException e) {
System.out.println("JNDI look up failed:" + e.getMessage());
System.exit(1);
}
// receive Messages and finally release the resources.
try {
connection = connectionFactory.createConnection();
connection.start(); // connection should be called in
// receiver-client
session = connection.createSession(Boolean.TRUE,
Session.SESSION_TRANSACTED);
consumer = session.createConsumer(destination); long timeout = 5 * 1000; // timeout:5 seconds
for (Message message = consumer.receive(timeout); message != null; message = consumer.receive(timeout)) {
String text = ((TextMessage) message).getText();
System.out.println(text);
} if (isIntentional()) {
throw new JMSException("这是一个故意抛出的异常。");
} session.commit();
} catch (JMSException e) {
try {
session.rollback();
} catch (JMSException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
try {
if (session != null)
session.close();
if (connection != null)
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}

TransactedConsumer.java

AMQ学习笔记 - 17. 事务的测试的更多相关文章

  1. AMQ学习笔记 - 18. 持久化的测试

    概述 对持久化的有效性进行测试. 测试实例 测试实例 结果预测 持久化递送 重启ActiveMQ后,消息还在队列中 非持久化递送 重启ActiveMQ后,消息不在队列中 demo设计 jms-prod ...

  2. CUBRID学习笔记17 事务的回滚

    语法:ROLLBACK [ WORK ] 下面的语句会报错 ALTER TABLE code DROP s_name; INSERT INTO code (s_name, f_name) VALUES ...

  3. 软件测试之loadrunner学习笔记-01事务

    loadrunner学习笔记-01事务<转载至网络> 事务又称为Transaction,事务是一个点为了衡量某个action的性能,需要在开始和结束位置插入一个范围,定义这样一个事务. 作 ...

  4. Ext.Net学习笔记17:Ext.Net GridPanel Selection

    Ext.Net学习笔记17:Ext.Net GridPanel Selection 接下来是Ext.Net的GridPanel的另外一个功能:选择. 我们在GridPanel最开始的用法中已经见识过如 ...

  5. WCF学习笔记之事务编程

    WCF学习笔记之事务编程 一:WCF事务设置 事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元: WCF通过System.ServiceModel.TransactionFlowA ...

  6. SQL反模式学习笔记17 全文搜索

    目标:全文搜索 使用SQL搜索关键字,同时保证快速和精确,依旧是相当地困难. SQL的一个基本原理(以及SQL所继承的关系原理)就是一列中的单个数据是原子性的. 反模式:模式匹配 使用Like 或者正 ...

  7. golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍

    golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍 go语言爬虫框架:gocolly/colly,goquery,colly,chrom ...

  8. MySQL实战45讲学习笔记:事务隔离级别(第三讲)

    一.隔离性与隔离级别 1.事务的特性 原子性 一致性 隔离性 持久性 2.不同事务隔离级别的区别 读未提交:别人改数据的事务尚未提交,我在我的事务中也能读到.读已提交:别人改数据的事务已经提交,我在我 ...

  9. AMQ学习笔记 - 06. 可靠消息传送

    概述 本文介绍JMS中可能发生消息故障的3个隐患阶段,以及确保消息安全的3种保障机制. 故障分析 在介绍可靠传送的确保机制之前,先分析消息在传送的过程中可能在哪个阶段出现问题. 1.两个跃点 跃点的含 ...

随机推荐

  1. 将表中数据生成SQL语句

    在开发过程中,经常需要我们对表中的数据进行转移,如果在同台机器,可以使用SQL自带的导入数据,但是如果想让所有的数据生成可执行的SQL语句,它的移植性最强了.首先要设计一个存储过程.具体如下: CRE ...

  2. GPS获取Location 获取所在地点的经纬度

    利用手机获取所在地点的经纬度: Location 在Android 开发中还是经常用到的,比如 通过经纬度获取天气,根据Location 获取所在地区详细Address (比如Google Map 开 ...

  3. 摘录知乎上关于android开发的话题精华

    1.初学者学习 Android 开发,有什么好网站推荐? http://www.zhihu.com/question/19611325 2.Android 开发有哪些新技术出现? http://www ...

  4. ls显示文件大小时显示单位

    在Linux中显示文件大小的时候,通常的做法是使用“ls -l”,显示的大小是文件的字节大小. 但是,如果文件比较大的话,显示起来不是特别易读,这个时候,可以使用“ls -lh”,就可以使用比较接近文 ...

  5. Good subsequence( RMQ+二分)

    Description Give you a sequence of n numbers, and a number k you should find the max length of Good ...

  6. [原创] Web UI 自动化日期控件的处理

    序 在构建自动化套件的过程中,日期操作是一件很重要也很频繁的事情.有的日期控件的div层级结构复杂,同一个类型的日期控件在多个子系统中的表现形式也大相径庭.多数工程师为了避免重复的工作,会封装抽象一个 ...

  7. 【谷歌市场安装】Google Play 闪退问题解决

    Google Play 安装后闪退,是因为手机没有内置GMS(Google Mobile Service) 框架. 由于谷歌退出了中国市场,国产手机很多都没有内置GMS, 导致Google Play ...

  8. (转)JavaScript 中对变量和函数声明的“提前(hoist)”

    变量声明“被提前” JavaScript 的语法和 C .Java.C# 类似,统称为 C 类语法.有过 C 或 Java 编程经验的同学应该对“先声明.后使用”的规则很熟悉,如果使用未经声明的变量或 ...

  9. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '

    mysql中如果字段使用了关键字,在插入和更新时会提示 You have an error in your SQL syntax; check the manual that corresponds ...

  10. 转: android apk 防止反编译技术(1~5连载)

    转: android apk 防止反编译技术 做android framework方面的工作将近三年的时间了,现在公司让做一下android apk安全方面的研究,于是最近就在网上找大量的资料来学习. ...