單元測試

控制層測試

這一層是針對接口的測試

使用技術

  1. MockMVC

    http://www.itdecent.cn/p/91045b0415f0

  2. Mokcito

    https://github.com/hehonghui/mockito-doc-zh

示例

測試方法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();
    }

    /**
     * 批量獲取學生作業(yè)的學生答題筆記
     *
     * schoolId 學校ID(默認為0查全部)
     * size 獲取條數(shù)
     * subject 學科(默認為0查全部)
     * lastTime 上次獲取的最小createTime(毫秒)
     */
    @Test
    public void findWorkList() throws Exception {
        //準備數(shù)據(jù)
        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();
    }
}

業(yè)務邏輯層測試

使用技術

Mokcito

示例

public class StudentWorkServiceTest {
    @InjectMocks
    private StudentWorkAppService studentWorkAppService;

    @Mock
    private StudentWorkRepository studentWorkRepository;

    @Mock
    private FileManager fileManager;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    /**
     * 批量獲取學生作業(yè)的學生答題筆記
     * <p>
     * schoolId 學校ID(默認為0查全部)
     * size 獲取條數(shù)
     * subject 學科(默認為0查全部)
     * lastTime 上次獲取的最小createTime(毫秒)
     */
    @Test
    public void findWorkList() throws Exception {
        //準備數(shù)據(jù)
        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");
        //校驗方法的運行次數(shù)
        verify(fileManager, times(1)).analysisSubmitContentUrl(studentWorks.get(1).getSubmitContentUrl());
        verify(fileManager, times(1)).analysisSingleTopicUrl(studentWorks.get(0).getAnswers().iterator().next().getTopicTraceUrl());
    }
}

持久層測試

數(shù)據(jù)庫選用

Fongo

? Fongo是MongoDB的內存Java實現(xiàn)。它攔截對標準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進行連接數(shù)據(jù)庫

@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靈活混用,所以放棄這種數(shù)據(jù)庫,因為一個是對象創(chuàng)建的MongoTemplate,一個是uri創(chuàng)建的MongoTemplate,在使用過程中還需要切換運行的代碼。

Embed Mongo

為在單元測試中運行mongodb提供一種平臺中立的方式,本質上是運行之前下載一個mongodb數(shù)據(jù)庫,下載的數(shù)據(jù)庫版本可以進行設置,使用之后數(shù)據(jù)清除,運行過程中可以使用可視化工具進行連接

使用
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();
    }
}
image-20200116111640179.png

如上例,只需要切換ActiveProfiles就可以靈活的切換數(shù)據(jù)庫進行測試

示例

@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(){
        //根據(jù)下列這些字段進行查詢
        //long schoolId, long classId, long teacherId, int subject,
        //List<Integer> periods, String bookId, int size, long lastTime, long startTime, long endTime
        //準備數(shù)據(jù)
        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();
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容