#
https://github.com/spring-projects/spring-sync-samples/tree/master/spring-rest-todos
package todos;
import static org.hamcrest.Matchers.*;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* @author Roy Clarkson
*/
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = Application.class)
@Ignore
public class MainControllerTest {
@Autowired
private WebApplicationContext context;
@Mock
private TodoRepository repository;
@InjectMocks
TodoController mainController;
private MockMvc mvc;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(mainController).build();
}
@Test
public void testList() throws Exception {
final Todo a = new Todo(1L, "a", false);
final Todo b = new Todo(2L, "b", false);
final Todo c = new Todo(3L, "c", false);
when(repository.findAll()).thenReturn(Arrays.asList(a, b, c));
mvc.perform(get("/todos")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(3)))
.andExpect(jsonPath("$[0].id", is(1)))
.andExpect(jsonPath("$[0].description", is("a")))
.andExpect(jsonPath("$[0].complete", is(false)))
.andExpect(jsonPath("$[1].id", is(2)))
.andExpect(jsonPath("$[1].description", is("b")))
.andExpect(jsonPath("$[1].complete", is(false)))
.andExpect(jsonPath("$[2].id", is(3)))
.andExpect(jsonPath("$[2].description", is("c")))
.andExpect(jsonPath("$[2].complete", is(false)));
verify(repository, times(1)).findAll();
verifyNoMoreInteractions(repository);
}
@Ignore
@Test
public void testPatch() throws Exception {
}
@Test
public void testCreate() throws Exception {
final Todo todo = new Todo(1L, "a", false);
ObjectMapper objectMapper = new ObjectMapper();
final byte[] bytes = objectMapper.writeValueAsBytes(todo);
when(repository.save(Mockito.any(Todo.class))).thenReturn(todo);
mvc.perform(post("/todos")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(bytes))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id", is(1)))
.andExpect(jsonPath("$.description", is("a")))
.andExpect(jsonPath("$.complete", is(false)));
verify(repository, times(1)).save(Mockito.any(Todo.class));
verifyNoMoreInteractions(repository);
}
@Test
public void testUpdateSameIds() throws Exception {
final Todo updatedTodo = new Todo(1L, "z", true);
ObjectMapper objectMapper = new ObjectMapper();
byte[] bytes = objectMapper.writeValueAsBytes(updatedTodo);
when(repository.save(Mockito.any(Todo.class))).thenReturn(updatedTodo);
mvc.perform(put("/todos/{id}", 1L)
.contentType(MediaType.APPLICATION_JSON)
.content(bytes))
.andExpect(status().isNoContent());
verify(repository, times(0)).delete(1L);
verify(repository, times(1)).save(Mockito.any(Todo.class));
verifyNoMoreInteractions(repository);
}
@Test
public void testUpdateDifferentIds() throws Exception {
final Todo updatedTodo = new Todo(99L, "z", true);
ObjectMapper objectMapper = new ObjectMapper();
byte[] bytes = objectMapper.writeValueAsBytes(updatedTodo);
when(repository.save(Mockito.any(Todo.class))).thenReturn(updatedTodo);
mvc.perform(put("/todos/{id}", 1L)
.contentType(MediaType.APPLICATION_JSON)
.content(bytes))
.andExpect(status().isNoContent());
verify(repository, times(1)).delete(1L);
verify(repository, times(1)).save(Mockito.any(Todo.class));
verifyNoMoreInteractions(repository);
}
@Test
public void testDelete() throws Exception {
// this is how to test a void method with Mockito
// doThrow(new IllegalArgumentException()).when(repository).delete(null);
mvc.perform(delete("/todos/{id}", 1L))
.andExpect(status().isNoContent());
}
}
关于系统用例的书籍,太多。不想在这里去解释什么是系统用例。但为什么要写系统用例呢,又如何写好呢?
写系统用例是为了更清晰的展示系统的业务场景的功能实现。也是为了给程序员参考的一个图。同时也是与客户沟通的桥梁。很多东西,千言万语,不如一张图那么直观。但在很多项目中,用例分析这个过程被忽略而过。
程序员往往只看到文本的需求,就自己开始做了,对于小项目或许这样可以,如果是大项目,后期肯定崩溃。
一个良好的系统用例,用图形的方式描述了客户的要求:
1. 有那些人去参与这个事件。
2.这些人具体要做什么 (可以理解为调用的方法)
3.这些人做这个事情,需要什么先决条件 (可以理解为参数,包括权限等等)
4.这些在做这些事情的时候,需要第三方帮忙吗?或者需要第三方系统接口吗?
5.做完这些事情,应该达到一个什么样的目的,也就是结果,这个结果会是下一个用例的输入吗?
当你有着人物,事件,参数,输入,输出的一张图 摆在眼前的时候,所有的事情的都清晰了。
看着这张图,就可以写出 相关的接口程序,实现方法等。
通过大量的系统用例,可以提取出公共的用例,比如权限等。从而抽象出公共的实现方法,才不会导致同一个方法,不同的程序员各自实现了一套。
以图书为例子,列表说明一个用例的主要部分,以及要表达清楚的地方。
用例名称 | bu_借阅图书 |
用例描述 | 借阅人通过此用例向系统查询并提交借书请求 |
执行者 | 借阅人 |
前置条件 | 1. 借阅人借阅证件在有效期内 2. 借阅人没有逾期未归还的图书 |
后置条件 | 1. 创建借书定单 2. 更新借阅人借阅记录 |
主过程描述 | 1用户用借阅证提供的帐号登录系统,计算机显示我的图书馆界面 2.用户选择查询图书,计算机显示查询界面 3.用户按书名、作者、出版社查询,计算机显示查询结果 4.用户可单选或多选书本,并确认借阅。计算机显示确认借阅图书清单。 5.用户选择确认借阅,计算机显示借阅定单及费用 6用户选择提交定单,计算机显示提交结果和定单号 7.计算机执行后置条件。用例结束 |
分支过程描述 | 2.1.1用户选择查看原有定单,计算机执行4; 4.1.1用户可单选或多选书本,放入借书篮,计算机显示借书篮现有内容 4.1.2.1.1用户选择继续借书,计算机执行2; 4.1.2.2.1用户选择提交借书篮,计算机执行4 4.2.1 用户选择放弃,计算机执行2; 6.1.1用户选择保存定单,计算机保存并执行1; 6.2.1用户选择放弃,计算机执行1; |
异常过程描述 | 1.1.1借阅证已过期,拒绝登录,用例结束 1.2.1借阅人有逾期未归还书本,启动bu_归还图书用例 5.1.1用户余额不足,计算机显示余额和所需金额 5.1.2.1.1用户选择续费,启动bu_交纳借阅费用例 5.1.2.2.1用户选择放弃,计算机执行1 |
业务规则 | 4.至少选择一本,至多选择三本 |
涉及的业务实体 | Be_费用记录 Be_图书 Be_借书篮 Be_借阅定单 Be_借阅证 |
启动STORAGE SERVER
fdfs_storaged /etc/fdfs/storage.conf
启动TRACKER SERVER
fdfs_trackerd /etc/fdfs/tracker.conf
启动NGINX
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
观看LOG
tail -f /home/storage1/fastdfs/logs/storaged.log
检查STORAGE SERVER
fdfs_monitor /etc/fdfs/client.conf
删除STORAGE SERVER
fdfs_monitor /etc/fdfs/client.conf delete group1 10.120.151.114
重启
/usr/local/bin/restart.sh fdfs_storaged /etc/fdfs/storage.conf
/usr/local/bin/restart.sh fdfs_trackerd /etc/fdfs/storage.conf
停止
/usr/local/bin/stop.sh fdfs_storaged /etc/fdfs/storage.conf
/usr/local/bin/stop.sh fdfs_trackerd /etc/fdfs/storage.conf
测试上传
fdfs_test /etc/fdfs/client.conf upload /usr/include/stdlib.h
查询文件是否存在
fdfs_file_info /etc/fdfs/client.conf group1/M00/00/D1/CniXclQ0vdfCNdkzAABGC4v7nb4822.png
STORAGE SERVER的状态通常有七种:
# FDFS_STORAGE_STATUS:INIT :初始化,尚未得到同步已有数据的源服务器
# FDFS_STORAGE_STATUS:WAIT_SYNC :等待同步,已得到同步已有数据的源服务器
# FDFS_STORAGE_STATUS:SYNCING :同步中
# FDFS_STORAGE_STATUS:DELETED :已删除,该服务器从本组中摘除
# FDFS_STORAGE_STATUS:OFFLINE :离线
# FDFS_STORAGE_STATUS:ONLINE :在线,尚不能提供服务
# FDFS_STORAGE_STATUS:ACTIVE :在线,可以提供服务
正常状态必须是ACTIVE,如果运行以下命令:
fdfs_monitor /etc/fdfs/client.conf
发现有以下状态的服务器:
Storage 4:
ip_addr = 10.120.151.114 WAIT_SYNC
经过各种重启都不解决问题,只好先删除,再加入
#从集群中删除
fdfs_monitor /etc/fdfs/client.conf delete group1 10.120.151.114
#在114服务器中,删除数据文件夹
rm -rf /home/storage1/fastdfs/data
#重启114节点
fdfs_storaged /etc/fdfs/storage.conf
重新查状态
fdfs_monitor /etc/fdfs/client.conf
状态变正常了。
摘要: FastDFS分布式文件系统的安装及配置
整体网络配置
1
Tracker Server 192.168.127.11 /home/fastdfs/trac...
阅读全文
今天发现服务器上Tomcat 8080端口起不来,老提示端口已经被占用。
使用命令:
ps -aux | grep tomcat
发现并没有8080端口的Tomcat进程。
使用命令:netstat –apn
查看所有的进程和端口使用情况。发现下面的进程列表,其中最后一栏是PID/Program name

发现8080端口被PID为9658的Java进程占用。
进一步使用命令:ps -aux | grep java,或者直接:ps -aux | grep pid 查看

就可以明确知道8080端口是被哪个程序占用了!然后判断是否使用KILL命令干掉!
方法二:直接使用 netstat -anp | grep portno
即:netstat –apn | grep 8080
摘要: 一、 安装tracker_server1、安装libevent卸载原有的lineventyum -y remove libeventwget http://down1.chinaunix.net/distfiles/libevent-1.4.12-stable.tar.gztar xvf libevent1.4.12-stable.tar.gzcd libevent./conf...
阅读全文