控制层测试
这一层是针对接口的测试
使用技术
示例
测试方法com.xh.cloudworkstatistic.application.StudentWorkAppService#getStuWorkWritingContent
@ActiveProfiles("local")
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class StudentWorkCtrlTest {
//将@Mock注解的对象注入到studentWorkCtrl下
@InjectMocks
private StudentWorkCtrl studentWorkCtrl;
@Mock
private StudentWorkAppService studentWorkAppService;
private MockMvc mockMvc;
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(studentWorkCtrl).build();
}
/**
* 批量获取学生作业的学生答题笔记
*
* schoolId 学校ID(默认为0查全部)
* size 获取条数
* subject 学科(默认为0查全部)
* lastTime 上次获取的最小createTime(毫秒)
*/
@Test
public void findWorkList() throws Exception {
//准备数据
long schoolId = 0L;
int size = 10;
int subject = 0;
long lastTime = 1511718859000L;
List<TopicHandWritingContent> contents = Lists.newArrayListWithExpectedSize(1);
TopicHandWritingContent topicHandWritingContent = new TopicHandWritingContent();
topicHandWritingContent.setTopicId("10086");
contents.add(topicHandWritingContent);
//mock,打桩
when(studentWorkAppService.getStuWorkWritingContent(schoolId,size,subject,lastTime)).thenReturn(contents);
//调用
mockMvc.perform(MockMvcRequestBuilders.get("/intranet/studentWorks/schools/"+schoolId+"/")
.accept(MediaType.APPLICATION_JSON_UTF8_VALUE)
.param("size",size+"")
.param("subject",subject+"")
.param("lastTime",lastTime+""))
//打印调用结果
.andDo(MockMvcResultHandlers.print())
//校验
.andExpect(MockMvcResultMatchers.content().string("[{\"topicId\":\"10086\",\"handWritingContents\":[]}]"))
.andReturn();
}
}
业务逻辑层测试
使用技术
Mokcito
示例
public class StudentWorkServiceTest {
@InjectMocks
private StudentWorkAppService studentWorkAppService;
@Mock
private StudentWorkRepository studentWorkRepository;
@Mock
private FileManager fileManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
/**
* 批量获取学生作业的学生答题笔记
* <p>
* schoolId 学校ID(默认为0查全部)
* size 获取条数
* subject 学科(默认为0查全部)
* lastTime 上次获取的最小createTime(毫秒)
*/
@Test
public void findWorkList() throws Exception {
//准备数据
long schoolId = 0L;
int size = 10;
int subject = 0;
long lastTime = 1511718859000L;
List<StudentWork> studentWorks = Lists.newArrayListWithCapacity(1);
StudentWork studentWork1 = new StudentWork();
studentWork1.setWorkVersion(1);
studentWork1.setSubmitContentUrl("a");
Set<Answer> answers = Sets.newHashSet();
Answer answer = new Answer();
answer.setTopicTraceUrl("http://www.baidu.com/");
answer.setTopicId("t1");
answers.add(answer);
studentWork1.setAnswers(answers);
studentWorks.add(studentWork1);
StudentWork studentWork2 = new StudentWork();
studentWork2.setWorkVersion(0);
studentWork2.setSubmitContentUrl("b");
studentWork2.setAnswers(answers);
studentWorks.add(studentWork2);
Map<String, List<HandWritingContent>> stuHandWritingMap = Maps.newHashMap();
List<HandWritingContent> handWritingContents = Lists.newArrayListWithCapacity(1);
HandWritingContent handWritingContent = new HandWritingContent(1, "abc");
handWritingContents.add(handWritingContent);
stuHandWritingMap.put("topicId", handWritingContents);
//打桩
when(studentWorkRepository.findAllFields(schoolId, size, subject, lastTime)).thenReturn(studentWorks);
when(fileManager.analysisSubmitContentUrl(studentWorks.get(1).getSubmitContentUrl())).thenReturn(stuHandWritingMap);
when(fileManager.analysisSingleTopicUrl(studentWorks.get(0).getAnswers().iterator().next().getTopicTraceUrl())).thenReturn(handWritingContents);
//调用
List<TopicHandWritingContent> workWritingContent = studentWorkAppService.getStuWorkWritingContent(schoolId, size, subject, lastTime);
//断言
Assert.assertEquals(workWritingContent.get(0).getTopicId(), "t1");
Assert.assertEquals(workWritingContent.get(1).getTopicId(), "topicId");
//校验方法的运行次数
verify(fileManager, times(1)).analysisSubmitContentUrl(studentWorks.get(1).getSubmitContentUrl());
verify(fileManager, times(1)).analysisSingleTopicUrl(studentWorks.get(0).getAnswers().iterator().next().getTopicTraceUrl());
}
}
持久层测试
数据库选用
Fongo
Fongo是MongoDB的内存Java实现。它拦截对标准mongo-java-driver的调用,以查找,更新,插入,移除和其他方法。主要用途是用于不想启动mongod
进程的轻量级单元测试。
使用
Fongo fongo = new Fongo("mongo server 1");
DB db = fongo.getDB("mydb");
DBCollection collection = db.getCollection("mycollection");
collection.insert(new BasicDBObject("name", "jon"));
整合SpringBoot
不能使用url进行连接数据库
@Configuration
public class MongoTestConfiguration {
@Bean
public Fongo fongo(){
return new Fongo("InMemoryMongo");
}
@Bean
public MongoClient mongo(){
return fongo().getMongo();
}
@Bean
public MongoTemplate mongoTemplate(){
return new MongoTemplate(mongo(),"test");
}
}
由于使用Fongo不能和原项目中的Mongo灵活混用,所以放弃这种数据库,因为一个是对象创建的MongoTemplate,一个是uri创建的MongoTemplate,在使用过程中还需要切换运行的代码。
Embed Mongo
为在单元测试中运行mongodb提供一种平台中立的方式,本质上是运行之前下载一个mongodb数据库,下载的数据库版本可以进行设置,使用之后数据清除,运行过程中可以使用可视化工具进行连接
使用
spring:
data:
mongodb:
uri: mongodb://localhost:12345/xh_cloudwork_test
exam:
uri: mongodb://localhost:12345/xh_cloudwork_exam
@Configuration
public class MongoTestConfiguration {
@Value("${spring.data.mongodb.uri}")
private String uri;
@Value("${spring.data.mongodb.exam.uri}")
private String examUri;
@Bean(name = "mongoTemplate")
public MongoTemplate getDefaultMongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory(uri));
}
@Bean(name = "examMongoTemplate")
public MongoTemplate examMongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory(examUri));
}
private MongoDbFactory mongoDbFactory(String uri) throws Exception {
return new SimpleMongoDbFactory(new MongoClientURI(uri));
}
}
@ActiveProfiles("unit")
@RunWith(SpringRunner.class)
@SpringBootTest(classes={TestApp.class})
public class TestDemo {
@Autowired
MongoTemplate mongoTemplate;
@Autowired
MongoTemplate examMongoTemplate;
MongodProcess mongod = null;
@Before
public void setUp() throws IOException {
MongodStarter starter = MongodStarter.getDefaultInstance();
String bindIp = "localhost";
int port = 12345;
IMongodConfig mongodConfig = new MongodConfigBuilder()
.version(Version.Main.PRODUCTION)
.net(new Net(bindIp, port, Network.localhostIsIPv6()))
.timeout(new Timeout(1000))
.build();
MongodExecutable mongodExecutable = null;
try {
mongodExecutable = starter.prepare(mongodConfig);
mongod = mongodExecutable.start();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void test(){
Work work = new Work();
work.setHandIn(3);
work.setSchoolId(20);
work.setHandInEmendNum(5);
work.setState(1);
examMongoTemplate.insert(work);
mongoTemplate.insert(work);
Work work1 = workRepository.findById(work.getWorkId());
System.out.println(work1.getSchoolId());
}
@After
public void close(){
mongod.stop();
}
}
如上例,只需要切换ActiveProfiles就可以灵活的切换数据库进行测试
示例
@ActiveProfiles("unit")
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class StudentWorkDaoTest {
@Autowired
MongoTemplate mongoTemplate;
@Autowired
MongoTemplate examMongoTemplate;
@Autowired
WorkManager workManager;
MongodProcess mongod = null;
@Before
public void startMongo() throws IOException {
MongodStarter starter = MongodStarter.getDefaultInstance();
String bindIp = "localhost";
int port = 12345;
IMongodConfig mongodConfig = new MongodConfigBuilder()
.version(Version.Main.PRODUCTION)
.net(new Net(bindIp, port, Network.localhostIsIPv6()))
.timeout(new Timeout(1000))
.build();
MongodExecutable mongodExecutable = null;
try {
mongodExecutable = starter.prepare(mongodConfig);
mongod = mongodExecutable.start();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void findAll(){
//根据下列这些字段进行查询
//long schoolId, long classId, long teacherId, int subject,
//List<Integer> periods, String bookId, int size, long lastTime, long startTime, long endTime
//准备数据
setData();
List<Integer> periods = Lists.newArrayList();
periods.add(0);
periods.add(1);
List<Work> works = workManager.findAll(1, 123456, 36471,
2, periods, "book01", 12,
0L, 10L,
22345678930L);
Assert.assertEquals(works.size(),3);
}
private void setData(){
for (int i = 1; i < 13; i++) {
Work work = new Work();
Group group = new Group();
group.setGroupId(123456);
List<Group> groups = Lists.newArrayList();
groups.add(group);
work.setTargets(groups);
work.setSubject(i%4+1);
work.setPeriod(i%4);
work.setTeacherId(36471);
work.setTeacherName("张淑虹");
work.setState(1);
work.setHandInEmendNum(123);
work.setHandIn(4);
work.setSchoolId(i%2);
work.setCorrectNum(2);
Title title = new Title("5b6166b0adf6460542bda0ca","单测用例",36471);
List<Title> titles = Lists.newArrayList();
titles.add(title);
work.setTitles(titles);
Topic topic = new Topic();
topic.setTopicId("topic01");
topic.setScore(80);
topic.setType(i%3);
topic.setBookId("book01");
List<Topic> topics = Lists.newArrayList();
topics.add(topic);
work.setTopics(topics);
work.setCreateTime(12345678910L+i);
mongoTemplate.insert(work);
}
}
@After
public void close(){
mongod.stop();
}
}