MockMVC - 基于RESTful風(fēng)格的SpringMVC的測(cè)試

MockMVC - 基于RESTful風(fēng)格的SpringMVC的測(cè)試

對(duì)于前后端分離的項(xiàng)目而言,無(wú)法直接從前端靜態(tài)代碼中測(cè)試接口的正確性驯用,因此可以通過(guò)MockMVC來(lái)模擬HTTP請(qǐng)求⊥苑基于RESTful風(fēng)格SpringMVC的測(cè)試挖腰,我們可以測(cè)試完整的Spring MVC流程猴仑,即從URL請(qǐng)求到控制器處理宁脊,再到視圖渲染都可以測(cè)試榆苞。

快速入門-這個(gè)方法中包含了大多數(shù)的常見情況:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @AutoConfigureMockMvc
    public class CourseControllerTest {

        @Autowired
        private MockMvc mockMvc;

        //ObjectMapper是一個(gè)可以重復(fù)使用的對(duì)象
        @Autowired
        private ObjectMapper mapper;

        @Test
        public void courseListTest() throws Exception{
            mockMvc.perform(MockMvcRequestBuilders.get("/course"))
                .andExpect(MockMvcResultMatchers.status().isOk());
        }

        @Test
        public void createTest() throws Exception{
            String json = "{\"name\":\"Mock測(cè)試\",\"classHour\":\"4課時(shí)\",\"id\":\"rn:practice:Course:5af27fa5d34f435e581e5bbf\"}";
            //將json格式字符串轉(zhuǎn)換成Course對(duì)象里的屬性值
            Course course = mapper.readValue(json,Course.class);
            //perform,執(zhí)行一個(gè)RequestBuilders請(qǐng)求,會(huì)自動(dòng)執(zhí)行SpringMVC的流程并映射到相應(yīng)的控制器執(zhí)行處理
            mockMvc.perform(
                    //構(gòu)造一個(gè)post請(qǐng)求
                    MockMvcRequestBuilders.post("/course")
                    .contentType(MediaType.APPLICATION_JSON_UTF8)
                    //使用writeValueAsString()方法來(lái)獲取對(duì)象的JSON字符串表示
                    .content(mapper.writeValueAsString(course)))
            //andExpect街夭,添加ResultMathcers驗(yàn)證規(guī)則,驗(yàn)證控制器執(zhí)行完成后結(jié)果是否正確趁尼,【這是一個(gè)斷言】
            .andExpect(MockMvcResultMatchers.status().is(200))

            .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8))

            //假定返回的結(jié)果中砚殿,"name" 值為 "Mock測(cè)試2",如果不是的話似炎,會(huì)拋出異常java.lang.AssertionError羡藐,并給出期望值和實(shí)際值
            .andExpect(MockMvcResultMatchers.jsonPath("$.name").value("Mock測(cè)試2"))

            //添加ResultHandler結(jié)果處理器传睹,比如調(diào)試時(shí) 打印結(jié)果(print方法)到控制臺(tái)
            .andDo(print())

            //返回相應(yīng)的MvcResult
            .andReturn();
    }

原理:

一 MockMvcBuilder

MockMvcBuilder是用來(lái)構(gòu)造MockMvc的構(gòu)造器,其主要有兩個(gè)實(shí)現(xiàn):StandaloneMockMvcBuilderDefaultMockMvcBuilder,分別對(duì)應(yīng)兩種測(cè)試方式店印,即獨(dú)立安裝和集成Web環(huán)境測(cè)試(此種方式并不會(huì)集成真正的web環(huán)境包券,而是通過(guò)相應(yīng)的Mock API進(jìn)行模擬測(cè)試溅固,無(wú)須啟動(dòng)服務(wù)器)侍郭。對(duì)于我們來(lái)說(shuō)直接使用靜態(tài)工廠MockMvcBuilders創(chuàng)建即可。

1.集成Web環(huán)境方式

MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定WebApplicationContext爆捞,將會(huì)從該上下文獲取相應(yīng)的控制器并得到相應(yīng)的MockMvc煮甥;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:config/IncotermsRestServiceTest-context.xml")
@WebAppConfiguration
public class IncotermsRestServiceTest {
    @Autowired
    private WebApplicationContext wac;
    private MockMvc mockMvc;
    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();   //構(gòu)造MockMvc
    }
    ...
}

注意:
    (1)@WebAppConfiguration:測(cè)試環(huán)境使用,用來(lái)表示測(cè)試環(huán)境使用的ApplicationContext將是WebApplicationContext類型的艇劫;value指定web應(yīng)用的根吼驶;
    (2)通過(guò)@Autowired WebApplicationContext wac:注入web環(huán)境的ApplicationContext容器;
    (3)然后通過(guò)MockMvcBuilders.webAppContextSetup(wac).build()創(chuàng)建一個(gè)MockMvc進(jìn)行測(cè)試店煞;

2.獨(dú)立測(cè)試方式

MockMvcBuilders.standaloneSetup(Object... controllers):通過(guò)參數(shù)指定一組控制器蟹演,這樣就不需要從上下文獲取了;
public class PricingExportResultsRestServiceTest {
    @InjectMocks
    private PricingExportResultsRestService pricingExportResultsRestService;
    @Mock
    private ExportRateScheduleService exportRateScheduleService;
    @Mock
    private PricingUrlProvider pricingUrlProvider;
    private MockMvc mockMvc;
    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(pricingExportResultsRestService).build();  //構(gòu)造MockMvc
    }
    ...
}

主要是兩個(gè)步驟:
(1)首先自己創(chuàng)建相應(yīng)的控制器顷蟀,注入相應(yīng)的依賴
(2)通過(guò)MockMvcBuilders.standaloneSetup模擬一個(gè)Mvc測(cè)試環(huán)境酒请,通過(guò)build得到一個(gè)MockMvc

二 MockMvc

先看一個(gè)測(cè)試?yán)?:

  @Test
    public void createIncotermSuccess() throws Exception {
        IncotermTo createdIncoterm = new IncotermTo();
        createdIncoterm.setId(new IncotermId(UUID.fromString("6305ff33-295e-11e5-ae37-54ee7534021a")));
        createdIncoterm.setCode("EXW");
        createdIncoterm.setDescription("code exw");
        createdIncoterm.setLocationQualifier(LocationQualifier.DEPARTURE);
when(inventoryService.create(any(IncotermTo.class))).thenReturn(createdIncoterm);   mockMvc.perform(post("/secured/resources/incoterms/create").accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON)
                .content("{\"code\" : \"EXW\", \"description\" : \"code exw\", \"locationQualifier\" : \"DEPARTURE\"}".getBytes()))
                //.andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("id.value").exists())
                .andExpect(jsonPath("id.value").value("6305ff33-295e-11e5-ae37-54ee7534021a"))
                .andExpect(jsonPath("code").value("EXW"));
    }

perform:執(zhí)行一個(gè)RequestBuilder請(qǐng)求,會(huì)自動(dòng)執(zhí)行SpringMVC的流程并映射到相應(yīng)的控制器執(zhí)行處理鸣个;
andExpect:添加ResultMatcher驗(yàn)證規(guī)則,驗(yàn)證控制器執(zhí)行完成后結(jié)果是否正確;
andDo:添加ResultHandler結(jié)果處理器,比如調(diào)試時(shí)打印結(jié)果到控制臺(tái);
andReturn:最后返回相應(yīng)的MvcResult;然后進(jìn)行自定義驗(yàn)證/進(jìn)行下一步的異步處理让腹;

看一個(gè)具體的例子2:

@Test  
public void testView() throws Exception {  
    MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/user/1"))  
            .andExpect(MockMvcResultMatchers.view().name("user/view"))  
            .andExpect(MockMvcResultMatchers.model().attributeExists("user"))  
            .andDo(MockMvcResultHandlers.print())  
            .andReturn();  
    Assert.assertNotNull(result.getModelAndView().getModel().get("user"));  
}  

整個(gè)過(guò)程:

  1. mockMvc.perform執(zhí)行一個(gè)請(qǐng)求驱犹;
  2. MockMvcRequestBuilders.get("/user/1")構(gòu)造一個(gè)請(qǐng)求
  3. ResultActions.andExpect添加執(zhí)行完成后的斷言
  4. ResultActions.andDo添加一個(gè)結(jié)果處理器俘侠,表示要對(duì)結(jié)果做點(diǎn)什么事情惫东,比如此處使用MockMvcResultHandlers.print()輸出整個(gè)響應(yīng)結(jié)果信息废封。
  5. ResultActions.andReturn表示執(zhí)行完成后返回相應(yīng)的結(jié)果。

整個(gè)測(cè)試過(guò)程非常有規(guī)律:

  1. 準(zhǔn)備測(cè)試環(huán)境
  2. 通過(guò)MockMvc執(zhí)行請(qǐng)求
  3. 添加驗(yàn)證斷言
    3.1 添加結(jié)果處理器
    3.2 得到MvcResult進(jìn)行自定義斷言/進(jìn)行下一步的異步請(qǐng)求
  4. 卸載測(cè)試環(huán)境

三 RequestBuilder/MockMvcRequestBuilders

從名字可以看出拂募,RequestBuilder用來(lái)構(gòu)建請(qǐng)求的,其提供了一個(gè)方法buildRequest(ServletContext servletContext)用于構(gòu)建MockHttpServletRequest论咏;其主要有兩個(gè)子類MockHttpServletRequestBuilderMockMultipartHttpServletRequestBuilder(如文件上傳使用)糊余,即用來(lái)Mock客戶端請(qǐng)求需要的所有數(shù)據(jù)。

1.MockMvcRequestBuilders主要API

MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables):根據(jù)uri模板和uri變量值得到一個(gè)GET請(qǐng)求方式的MockHttpServletRequestBuilder洼专;如get(/user/{id}, 1L)雾袱;

MockHttpServletRequestBuilder post(String urlTemplate, Object... urlVariables):同get類似煎殷,但是是POST方法剑梳;

MockHttpServletRequestBuilder put(String urlTemplate, Object... urlVariables):同get類似酪刀,但是是PUT方法;

MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables) :同get類似赵刑,但是是DELETE方法;

MockHttpServletRequestBuilder options(String urlTemplate, Object... urlVariables):同get類似瓤摧,但是是OPTIONS方法;

MockHttpServletRequestBuilder request(HttpMethod httpMethod, String urlTemplate, Object... urlVariables): 提供自己的Http請(qǐng)求方法及uri模板和uri變量皆辽,如上API都是委托給這個(gè)API盆耽;

MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object... urlVariables):提供文件上傳方式的請(qǐng)求匙姜,得到MockMultipartHttpServletRequestBuilder;

RequestBuilder asyncDispatch(final MvcResult mvcResult):創(chuàng)建一個(gè)從啟動(dòng)異步處理的請(qǐng)求的MvcResult進(jìn)行異步分派的RequestBuilder寸癌;

2.MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder API

(1)MockHttpServletRequestBuilder API

MockHttpServletRequestBuilder header(String name, Object... values)/MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders):添加頭信息;

MockHttpServletRequestBuilder contentType(MediaType mediaType):指定請(qǐng)求的contentType頭信息蒿秦;

MockHttpServletRequestBuilder accept(MediaType... mediaTypes)/MockHttpServletRequestBuilder accept(String... mediaTypes):指定請(qǐng)求的Accept頭信息炮叶;

MockHttpServletRequestBuilder content(byte[] content)/MockHttpServletRequestBuilder content(String content):指定請(qǐng)求Body體內(nèi)容;

MockHttpServletRequestBuilder cookie(Cookie... cookies):指定請(qǐng)求的Cookie渡处;

MockHttpServletRequestBuilder locale(Locale locale):指定請(qǐng)求的Locale镜悉;

MockHttpServletRequestBuilder characterEncoding(String encoding):指定請(qǐng)求字符編碼;

MockHttpServletRequestBuilder requestAttr(String name, Object value) :設(shè)置請(qǐng)求屬性數(shù)據(jù)医瘫;

MockHttpServletRequestBuilder sessionAttr(String name, Object value)/MockHttpServletRequestBuilder sessionAttrs(Map<string, object=""> sessionAttributes):設(shè)置請(qǐng)求session屬性數(shù)據(jù)侣肄;

MockHttpServletRequestBuilder flashAttr(String name, Object value)/MockHttpServletRequestBuilder flashAttrs(Map<string, object=""> flashAttributes):指定請(qǐng)求的flash信息,比如重定向后的屬性信息醇份;

MockHttpServletRequestBuilder session(MockHttpSession session) :指定請(qǐng)求的Session稼锅;

MockHttpServletRequestBuilder principal(Principal principal) :指定請(qǐng)求的Principal;

MockHttpServletRequestBuilder contextPath(String contextPath) :指定請(qǐng)求的上下文路徑僚纷,必須以“/”開頭矩距,且不能以“/”結(jié)尾;

MockHttpServletRequestBuilder pathInfo(String pathInfo) :請(qǐng)求的路徑信息怖竭,必須以“/”開頭锥债;

MockHttpServletRequestBuilder secure(boolean secure):請(qǐng)求是否使用安全通道;

MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor):請(qǐng)求的后處理器,用于自定義一些請(qǐng)求處理的擴(kuò)展點(diǎn)赞弥;

(2)MockMultipartHttpServletRequestBuilder

繼承自MockHttpServletRequestBuilder毅整,又提供了如下API
MockMultipartHttpServletRequestBuilder file(String name, byte[] content)/MockMultipartHttpServletRequestBuilder file(MockMultipartFile file):指定要上傳的文件趣兄;

四 ResultActions

調(diào)用MockMvc.perform(RequestBuilder requestBuilder)后將得到ResultActions绽左,通過(guò)ResultActions完成如下三件事:
ResultActions andExpect(ResultMatcher matcher) :添加驗(yàn)證斷言來(lái)判斷執(zhí)行請(qǐng)求后的結(jié)果是否是預(yù)期的;
ResultActions andDo(ResultHandler handler) :添加結(jié)果處理器艇潭,用于對(duì)驗(yàn)證成功后執(zhí)行的動(dòng)作拼窥,如輸出下請(qǐng)求/結(jié)果信息用于調(diào)試;
MvcResult andReturn() :返回驗(yàn)證成功后的MvcResult蹋凝;用于自定義驗(yàn)證/下一步的異步處理鲁纠;

五 ResultMatcher/MockMvcResultMatchers

1.ResultMatcher用來(lái)匹配執(zhí)行完請(qǐng)求后的結(jié)果驗(yàn)證,其就一個(gè)match(MvcResult result)斷言方法鳍寂,如果匹配失敗將拋出相應(yīng)的異常改含;spring mvc測(cè)試框架提供了很多***ResultMatchers來(lái)滿足測(cè)試需求。注意這些***ResultMatchers并不是ResultMatcher的子類迄汛,而是返回ResultMatcher實(shí)例的捍壤。Spring mvc測(cè)試框架為了測(cè)試方便提供了MockMvcResultMatchers靜態(tài)工廠方法方便操作;

2.具體的API如下:

HandlerResultMatchers handler():請(qǐng)求的Handler驗(yàn)證器鞍爱,比如驗(yàn)證處理器類型/方法名鹃觉;此處的Handler其實(shí)就是處理請(qǐng)求的控制器;

RequestResultMatchers request():得到RequestResultMatchers驗(yàn)證器睹逃;

ModelResultMatchers model():得到模型驗(yàn)證器盗扇;

ViewResultMatchers view():得到視圖驗(yàn)證器;

FlashAttributeResultMatchers flash():得到Flash屬性驗(yàn)證沉填;

StatusResultMatchers status():得到響應(yīng)狀態(tài)驗(yàn)證器疗隶;

HeaderResultMatchers header():得到響應(yīng)Header驗(yàn)證器;

CookieResultMatchers cookie():得到響應(yīng)Cookie驗(yàn)證器翼闹;

ContentResultMatchers content():得到響應(yīng)內(nèi)容驗(yàn)證器斑鼻;

JsonPathResultMatchers jsonPath(String expression, Object ... args)/ResultMatcher jsonPath  (String expression, Matcher matcher):得到Json表達(dá)式驗(yàn)證器;

XpathResultMatchers xpath(String expression, Object... args)/XpathResultMatchers xpath(String expression, Map<string, string=""> namespaces, Object... args):得到Xpath表達(dá)式驗(yàn)證器橄碾;

ResultMatcher forwardedUrl(final String expectedUrl):驗(yàn)證處理完請(qǐng)求后轉(zhuǎn)發(fā)的url(絕對(duì)匹配)卵沉;

ResultMatcher forwardedUrlPattern(final String urlPattern):驗(yàn)證處理完請(qǐng)求后轉(zhuǎn)發(fā)的url(Ant風(fēng)格模式匹配,@since spring4)法牲;

ResultMatcher redirectedUrl(final String expectedUrl):驗(yàn)證處理完請(qǐng)求后重定向的url(絕對(duì)匹配)史汗;

ResultMatcher redirectedUrlPattern(final String expectedUrl):驗(yàn)證處理完請(qǐng)求后重定向的url(Ant風(fēng)格模式匹配,@since spring4)

六 一些常用的測(cè)試

1.測(cè)試普通控制器

mockMvc.perform(get("/user/{id}", 1)) //執(zhí)行請(qǐng)求  
        .andExpect(model().attributeExists("user")) //驗(yàn)證存儲(chǔ)模型數(shù)據(jù)  
        .andExpect(view().name("user/view")) //驗(yàn)證viewName  
        .andExpect(forwardedUrl("/WEB-INF/jsp/user/view.jsp"))//驗(yàn)證視圖渲染時(shí)forward到的jsp  
        .andExpect(status().isOk())//驗(yàn)證狀態(tài)碼  
        .andDo(print()); //輸出MvcResult到控制臺(tái)

2.得到MvcResult自定義驗(yàn)證

MvcResult result = mockMvc.perform(get("/user/{id}", 1))//執(zhí)行請(qǐng)求  
        .andReturn(); //返回MvcResult  
Assert.assertNotNull(result.getModelAndView().getModel().get("user")); //自定義斷言   

3.驗(yàn)證請(qǐng)求參數(shù)綁定到模型數(shù)據(jù)及Flash屬性

mockMvc.perform(post("/user").param("name", "zhang")) //執(zhí)行傳遞參數(shù)的POST請(qǐng)求(也可以post("/user?name=zhang"))  
            .andExpect(handler().handlerType(UserController.class)) //驗(yàn)證執(zhí)行的控制器類型  
            .andExpect(handler().methodName("create")) //驗(yàn)證執(zhí)行的控制器方法名  
            .andExpect(model().hasNoErrors()) //驗(yàn)證頁(yè)面沒有錯(cuò)誤  
            .andExpect(flash().attributeExists("success")) //驗(yàn)證存在flash屬性  
            .andExpect(view().name("redirect:/user")); //驗(yàn)證視圖  

4.文件上傳

byte[] bytes = new byte[] {1, 2};  
mockMvc.perform(fileUpload("/user/{id}/icon", 1L).file("icon", bytes)) //執(zhí)行文件上傳  
        .andExpect(model().attribute("icon", bytes)) //驗(yàn)證屬性相等性  
        .andExpect(view().name("success")); //驗(yàn)證視圖  

5.JSON請(qǐng)求/響應(yīng)驗(yàn)證

String requestBody = "{\"id\":1, \"name\":\"zhang\"}";  
    mockMvc.perform(post("/user")  
            .contentType(MediaType.APPLICATION_JSON).content(requestBody)  
            .accept(MediaType.APPLICATION_JSON)) //執(zhí)行請(qǐng)求  
            .andExpect(content().contentType(MediaType.APPLICATION_JSON)) //驗(yàn)證響應(yīng)contentType  
            .andExpect(jsonPath("$.id").value(1)); //使用Json path驗(yàn)證JSON 請(qǐng)參考http://goessner.net/articles/JsonPath/   
    String errorBody = "{id:1, name:zhang}";  
    MvcResult result = mockMvc.perform(post("/user")  
            .contentType(MediaType.APPLICATION_JSON).content(errorBody)  
            .accept(MediaType.APPLICATION_JSON)) //執(zhí)行請(qǐng)求  
            .andExpect(status().isBadRequest()) //400錯(cuò)誤請(qǐng)求  
            .andReturn();   
    Assert.assertTrue(HttpMessageNotReadableException.class.isAssignableFrom(result.getResolvedException().getClass()));//錯(cuò)誤的請(qǐng)求內(nèi)容體

6.異步測(cè)試

//Callable  
MvcResult result = mockMvc.perform(get("/user/async1?id=1&name=zhang")) //執(zhí)行請(qǐng)求  
        .andExpect(request().asyncStarted())  
        .andExpect(request().asyncResult(CoreMatchers.instanceOf(User.class))) //默認(rèn)會(huì)等10秒超時(shí)  
        .andReturn();  
    
mockMvc.perform(asyncDispatch(result))  
        .andExpect(status().isOk())  
        .andExpect(content().contentType(MediaType.APPLICATION_JSON))  
        .andExpect(jsonPath("$.id").value(1));  

7.全局配置

mockMvc = webAppContextSetup(wac)  
        .defaultRequest(get("/user/1").requestAttr("default", true)) //默認(rèn)請(qǐng)求 如果其是Mergeable類型的拒垃,會(huì)自動(dòng)合并的哦mockMvc.perform中的RequestBuilder  
        .alwaysDo(print())  //默認(rèn)每次執(zhí)行請(qǐng)求后都做的動(dòng)作  
        .alwaysExpect(request().attribute("default", true)) //默認(rèn)每次執(zhí)行后進(jìn)行驗(yàn)證的斷言  
        .build();  
  
mockMvc.perform(get("/user/1"))  
        .andExpect(model().attributeExists("user"));  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末停撞,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌戈毒,老刑警劉巖艰猬,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異埋市,居然都是意外死亡冠桃,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門道宅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)食听,“玉大人,你說(shuō)我怎么就攤上這事污茵∮1ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵泞当,是天一觀的道長(zhǎng)迹蛤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)襟士,這世上最難降的妖魔是什么盗飒? 我笑而不...
    開封第一講書人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮敌蜂,結(jié)果婚禮上箩兽,老公的妹妹穿的比我還像新娘。我一直安慰自己章喉,他們只是感情好汗贫,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秸脱,像睡著了一般落包。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上摊唇,一...
    開封第一講書人閱讀 52,736評(píng)論 1 312
  • 那天咐蝇,我揣著相機(jī)與錄音,去河邊找鬼巷查。 笑死有序,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的岛请。 我是一名探鬼主播旭寿,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼崇败!你這毒婦竟也來(lái)了盅称?” 一聲冷哼從身側(cè)響起肩祥,我...
    開封第一講書人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缩膝,沒想到半個(gè)月后混狠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疾层,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年将饺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片云芦。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡俯逾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出舅逸,到底是詐尸還是另有隱情,我是刑警寧澤皇筛,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布琉历,位于F島的核電站,受9級(jí)特大地震影響水醋,放射性物質(zhì)發(fā)生泄漏旗笔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一拄踪、第九天 我趴在偏房一處隱蔽的房頂上張望蝇恶。 院中可真熱鬧,春花似錦惶桐、人聲如沸撮弧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贿衍。三九已至,卻和暖如春救恨,著一層夾襖步出監(jiān)牢的瞬間贸辈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工肠槽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留擎淤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓秸仙,卻偏偏與公主長(zhǎng)得像嘴拢,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子筋栋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理炊汤,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,716評(píng)論 18 139
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架抢腐,建立于...
    Hsinwong閱讀 22,443評(píng)論 1 92
  • 1姑曙、通過(guò)CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明先生_X自主閱讀 15,988評(píng)論 3 119
  • 案情:二手房買賣合同已簽署伤靠,合同約定總價(jià)款295萬(wàn)元,買家已支付定金20萬(wàn)元啼染,該案例發(fā)生在2015年宴合,因房?jī)r(jià)大幅攀...
    律大妞閱讀 549評(píng)論 0 0
  • 在 Objective-C 的世界里面經(jīng)常錯(cuò)過(guò)的一個(gè)東西是抽象接口。接口(interface)這個(gè)詞通常指一個(gè)類的...
    維維_iOS閱讀 240評(píng)論 0 0