概述


对事务机制进行测试。

测试实例


测试实例 结果预测
发送正常 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. C语言阶乘和求闰年

    #include<stdio.h> void main(){ int i,a,s=1; scanf("%d",&a); for(i=1;i<=a;i++) ...

  2. TP的一条sql语句(子查询)

    $model=M(''); $model->table(C('DB_PREFIX').'goods as g') ->join(C('DB_PREFIX').'orders as o on ...

  3. TP常用函数

    英文字符可用形如 {$vo.title|substr=0,5} 如果是中文字符thinkphp提供了msubstr如下 function msubstr($str, $start=0, $length ...

  4. [Angular2 Router] Programmatic Router Navigation via the Router API - Relative And Absolute Router Navigation

    In this tutorial we are going to learn how to navigate programmatically (or imperatively) by using t ...

  5. [Express] Level 4: Body-parser -- Delete

    Response Body What would the response body be set to on a DELETE request to /cities/DoesNotExist ? H ...

  6. jodd-StringTemplateParser使用

    StringTemplateParser 时一个string模板的解析器.在string模板中定义类似jsp标签的宏. 在解析过程中,宏被对值替换,值通过自定义的MacroResolver解析得到. ...

  7. 深入分析 Linux 内核链表--转

    引用地址:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 一. 链表数据结构简介 链表是一种常用的组织有序数据 ...

  8. BootStrap2学习日记21---消息提示

    <p><a href="#" title="中国(China),位于东亚,是一个以华夏文明为主体.中华文化为基础,以汉族为主要民族的统一多民族国家,通用 ...

  9. IIS 之 HTTP Error 404.2 – Not Found(ISAPI 和 CGI 限制)

    对于很多B/S架构的软件来说,在IIS中添加ISAPI和CGI限制功能是非常必要的,因为如果在IIS中不添加添加ISAPI和CGI限制功能可能会引起软件运行过程中报错,或者直接就登录不了. 1.允许I ...

  10. 虚拟机+ubuntu 图形界面和终端界面的切换

    虚拟机环境,在图形界面和文本界面间切换:1  VMWare虚拟机下,由图形界面切换到文本界面,和虚拟机设置有关,默认VM占用Ctrl+Alt为热键,所以由图形界面切换到文本界面的组合键为: Ctrl+ ...