RestAssured學習(一)

本帖內容摘抄自:https://testerhome.com/topics/7060,在此基礎上增加練習筆記(在看本帖之前可以先看原文檔)健盒。
注:本文中接口均是moco的接口改淑,請參考《Moco接口框架應用實戰(zhàn)》了解moco基本知識亮蛔。
REST Assured是一個可以簡化HTTP Builder頂層 基于REST服務的測試過程的Java DSL(針對某一領域痴施,具有受限表達性的一種計算機程序設計語言)。它支持發(fā)起POST,GET,PUT,DELETE,OPTIONS,PATCH和HEAD請求究流,并且可以用來驗證和校對這些請求的響應信息辣吃。

靜態(tài)導入方法:
pom.xml中要加入以下依賴:

        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>json-schema-validator</artifactId>
            <version>3.0.2</version>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>spring-mock-mvc</artifactId>
            <version>3.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-library</artifactId>
        </dependency>

推薦大家從以下的類中靜態(tài)導入方法,以提高使用rest-assured的效率芬探。

import io.restassured.RestAssured.*;
import io.restassured.matcher.RestAssuredMatchers.*;
import org.hamcrest.Matchers.*;

如果您想使用Json Schema validation 還應該靜態(tài)導入這些方法:

import io.restassured.module.jsv.JsonSchemaValidator.*;

更多使用方法參閱 Json Schema Validation 神得。

如果您正在使用SpringMVC,你可以使用spring-mock-mvc 模型的Rest Assured DSL來對Spring的controller層進行單元測試偷仿。為此需要從RestAssuredMockMvc靜態(tài)導入這些方法:

import io.restassured.module.mockmvc.RestAssuredMockMvc.*;

示例
例一 - JSON
假設某個get請求 (to http://localhost:8889/lotto) 返回JSON如下:

  {
    "description":"返回json接口",
    "request":{
      "uri":"/lotto",
      "method":"get"
    },
    "response":{
      "json":{
        "lotto":{
          "lottoId":5,
          "winning-numbers":[2,45,34,23,7,5,3],
          "winners":[{
            "winnerId":23,
            "numbers":[2,45,34,23,3,5]
          },{
            "winnerId":54,
            "numbers":[52,3,12,11,18,22]
          }]
        }
      }
    }
  }

REST assured可以幫您輕松地進行get請求并對響應信息進行處理哩簿。舉個例子,如果想要判斷l(xiāng)ottoId的值是否等于5酝静,你可以這樣做:
在類中寫一個方法节榜,寫下如下代碼:

    @Test
    public void testone(){
        given()
                .when()
                .get("http://localhost:8889/lotto")
                .then()
                .body("lotto.lottoId",equalTo(5));

    }

注:lottoId必須是int類型,才能用equalTo(5)别智,如果是string類型宗苍,用equalTo("5")
又或許您想要檢查winnerId的取值包括23和54:

    @Test
    public void testtwo(){
        given()
                .when()
                .get("http://localhost:8889/lotto")
                .then()
                .body("lotto.winners.winnerId",hasItems(23,54));

    }

注意: equalTo 和 hasItems 是 Hamcrest matchers的方法,所以需要靜態(tài)導入 import static org.hamcrest.Matchers.*;
注意這里的"json path"語法使用的是Groovy的GPath標注法薄榛,不要和Jayway的JsonPath語法混淆讳窟。(暫時可以不用關注)

以BigDecimal返回float和double類型
(譯者注:Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數(shù)進行精確的運算)

您可以對rest-assured和JsonPath進行配置敞恋,使之以BigDecimal返回json里的數(shù)值類型數(shù)據(jù)丽啡,而不是float或者double∮裁ǎ可以參考下面json文本:

  {
    "description":"以BigDecimal返回float和double類型",
    "request":{
      "uri":"/price",
      "method":"get"
    },
    "response":{
      "json":{
        "price":12.12
      }
    }
  }

默認情況下您驗證price字段是否等于float類型的12.12像這樣:

    @Test
    public void testthree(){
        given()
                .when()
                .get("http://localhost:8889/price")
                .then()
                .body("price",is(12.12f));

    }

但是如果想用rest-assured的JsonConfig來配置返回的所有的json數(shù)值都為BigDecimal類型:

    @Test
    public void testfour(){
        given()
                .config(RestAssured.config().jsonConfig(jsonConfig().numberReturnType(BIG_DECIMAL)))
                .when()
                .get("http://localhost:8889/price")
                .then()
                .body("price",is(new BigDecimal(12.12)));

    }

因為上面moco的接口沒有定義price是BigDecimal類型补箍,所以test的接口代碼會報錯,實際測試中遇到返回值類型是BigDecimal的可以用這個代碼啸蜜。

JSON Schema validation
自從 2.1.0 版本rest-assured開始支持Json Schema validation. 舉個例子馏予,在classpath中放置以下的schema文件(譯者注:idea的話可以放在resources目錄下),products-schema.json:

{
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "title": "The Root Schema",
  "required": [
    "lotto"
  ],
  "properties": {
    "lotto": {
      "$id": "#/properties/lotto",
      "type": "object",
      "title": "The Lotto Schema",
      "required": [
        "lottoId",
        "winning-numbers",
        "winners"
      ],
      "properties": {
        "lottoId": {
          "$id": "#/properties/lotto/properties/lottoId",
          "type": "integer",
          "title": "The Lottoid Schema",
          "default": 0,
          "examples": [
            5
          ]
        },
        "winning-numbers": {
          "$id": "#/properties/lotto/properties/winning-numbers",
          "type": "array",
          "title": "The Winning-numbers Schema",
          "items": {
            "$id": "#/properties/lotto/properties/winning-numbers/items",
            "type": "integer",
            "title": "The Items Schema",
            "default": 0,
            "examples": [
              2,
              45,
              34,
              23,
              7,
              5,
              3
            ]
          }
        },
        "winners": {
          "$id": "#/properties/lotto/properties/winners",
          "type": "array",
          "title": "The Winners Schema",
          "items": {
            "$id": "#/properties/lotto/properties/winners/items",
            "type": "object",
            "title": "The Items Schema",
            "required": [
              "winnerId",
              "numbers"
            ],
            "properties": {
              "winnerId": {
                "$id": "#/properties/lotto/properties/winners/items/properties/winnerId",
                "type": "integer",
                "title": "The Winnerid Schema",
                "default": 0,
                "examples": [
                  23
                ]
              },
              "numbers": {
                "$id": "#/properties/lotto/properties/winners/items/properties/numbers",
                "type": "array",
                "title": "The Numbers Schema",
                "items": {
                  "$id": "#/properties/lotto/properties/winners/items/properties/numbers/items",
                  "type": "integer",
                  "title": "The Items Schema",
                  "default": 0,
                  "examples": [
                    2,
                    45,
                    34,
                    23,
                    3,
                    5
                  ]
                }
              }
            }
          }
        }
      }
    }
  }
}

您可以使用這個schema驗證(/products)這個請求是否符合規(guī)范:

    @Test
    public void testfive(){
        given()
                .when()
                .get("http://localhost:8889/lotto")
                .then()
                .assertThat()
                .body(matchesJsonSchemaInClasspath("products-schema.json"));

    }

注:jsonschema 可以在https://www.jsonschema.net/網(wǎng)頁中生成盔性,
在resource包下創(chuàng)建products-schema.json,放入從網(wǎng)頁中生成的jsonschema呢岗。

matchesJsonSchemaInClasspath 靜態(tài)導入自 io.restassured.module.jsv.JsonSchemaValidator 并且我們推薦從這個類中靜態(tài)導入所有的方法冕香。

import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;

maven依賴蛹尝,上面已經(jīng)講過要加入該依賴:

        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>json-schema-validator</artifactId>
            <version>3.0.2</version>
        </dependency>

JSON Schema Validation 設置項

rest-assured的json-schema-validator module使用Francis Galiegue的json-schema-validator (fge) 庫來進行驗證。 如果您想配置使用基礎fge庫悉尾,你可以像下面例子中:

    @Test
    public void testsix(){
        // Given
        JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory.newBuilder().setValidationConfiguration(ValidationConfiguration.newBuilder().setDefaultVersion(DRAFTV4).freeze()).freeze();
        // When
        get("http://localhost:8889/lotto").then().assertThat().body(matchesJsonSchemaInClasspath("products-schema.json").using(jsonSchemaFactory));

    }

using方法允許您進入jsonSchemaFactory的實例突那,rest-assured在驗證期間也會進行此操作。這種方式允許我們對驗證進行細粒度的配置构眯。

fge庫也允許驗證狀態(tài)是 checked或者unchecked(譯者注:表示不懂)愕难。默認情況,rest-assured使用checked驗證惫霸,但是如果你想要改變這種方式猫缭,您可以提供一個matcher的JsonSchemaValidatorSettings實例。舉個例子:
get("/products").then().assertThat().body(matchesJsonSchemaInClasspath("products-schema.json").using(settings().with().checkedValidation(false)));
這些settings方法靜態(tài)導入自 JsonSchemaValidatorSettings類壹店。

注:想要驗證jsonschema猜丹,用testfive方法中寫的驗證就可以了。

Json Schema Validation的靜態(tài)配置

現(xiàn)在想象下您總是使用unchecked驗證硅卢,并且設置默認的json schema版本為3射窒。與其每次都在代碼里進行設置,不如靜態(tài)地進行定義設置将塑。舉個例子:

    @Test
    public void testeight(){
        JsonSchemaValidator.settings = settings().with().jsonSchemaFactory(
                JsonSchemaFactory.newBuilder().setValidationConfiguration(ValidationConfiguration.newBuilder().setDefaultVersion(DRAFTV3).freeze()).freeze()).
                and().with().checkedValidation(false);

        get("http://localhost:8889/lotto").then().assertThat().body(matchesJsonSchemaInClasspath("products-schema.json"));
    }

注:DRAFTV3 會報錯脉顿,DRAFTV4是可以成功的。

現(xiàn)在任意一個由JsonSchemaValidator導入的matcher都會使用DRAFTV3作為默認版本并且unchecked validation点寥。

想要重置JsonSchemaValidator到默認設置僅僅需要調用reset方法:

JsonSchemaValidator.reset();

不使用rest-assured的Json Schema Validation
您也可以在不依賴rest-assured的情況下使用json-schema-validator module艾疟。如想要把json文本表示為String類型的字符串,可以這樣做:

    @Test
    public void testnine(){

        String json = "{\n" +
                "        \"lotto\":{\n" +
                "          \"lottoId\":5,\n" +
                "          \"winning-numbers\":[2,45,34,23,7,5,3],\n" +
                "          \"winners\":[{\n" +
                "            \"winnerId\":23,\n" +
                "            \"numbers\":[2,45,34,23,3,5]\n" +
                "          },{\n" +
                "            \"winnerId\":54,\n" +
                "            \"numbers\":[52,3,12,11,18,22]\n" +
                "          }]\n" +
                "        }\n" +
                "      }";
        assertThat(json,matchesJsonSchemaInClasspath("products-schema.json"));
    }

匿名式的JSON根節(jié)點驗證
一個JSON文本并不總是有一個命名好的根屬性开财。這里有個驗證這種JSON的例子:
[1, 2, 3]

注:這種json的返回不太好設計汉柒,moco不出這樣的接口。

一個匿名的JSON根屬性可以通過使用$或者空字符串作為路徑來識別责鳍。舉個例子碾褂,通過訪問http://localhost:8889/json這個地址可以獲得一個JSON文本,我們可以使用rest-assured驗證:

    @Test
    public void testten(){
        given()
                .when()
                .get("http://localhost:8889/json")
                .then()
                .body("$",hasItems(1,2,3));

    }

例2 - XML
XML可以一種通過簡單的方式解析历葛。假設一個POST請求http://localhost:8080/greetXML返回:

  {
    "description":"返回內容是xml",
    "request":{
      "uri":"/getxml",
      "method":"post",
      "forms":{
        "firstName":"John",
        "lastName":"Doe"
      }
    },
    "response":{
      "text":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?> <greeting>\n<firstName>John</firstName>\n<lastName>Doe</lastName>\n</greeting>",
      "headers":{
        "Content-Type":"text/xml"
      }

    }
    }

換言之正塌,它在請求中返還了一個基于firstname和lastname請求參數(shù)的greeting節(jié)點。您可以通過rest-assured輕易地展現(xiàn)和解析這個例子

        //post入?yún)閒orm 表單參數(shù)恤溶,返回類型為xml
        given()
                .proxy(8888)//連接代理
                .formParam("firstName", "John")
                .formParam("lastName","Doe")
                .when()
                .post("http://localhost:8889/getxml")
                .then()
                .using()
                .defaultParser(Parser.XML)//返回類型是xml格式
                .body("greeting.firstName",equalTo("John"));//校驗結果

如果您想同時解析firstname和lastname可以這樣做:

        //post入?yún)閒orm 表單參數(shù)乓诽,返回類型為xml
        given()
                .proxy(8888)//連接代理
                .formParam("firstName", "John")
                .formParam("lastName","Doe")
                .when()
                .post("http://localhost:8889/getxml")
                .then()
                .using()
                .defaultParser(Parser.XML)//返回類型是xml格式
                .body("greeting.firstName",equalTo("John"))
                .body("greeting.lastName",equalTo("Doe"));//校驗結果

或者稍微簡短些:

        with().formParams("firstName", "John", "lastName", "Doe").when().post("http://localhost:8889/getxml").then().body("greeting.firstName", equalTo("John"), "greeting.lastName", equalTo("Doe"));

XML 命名空間

考慮到您需要使用io.restassured.config.XmlConfig聲明一個命名空間。舉個例子咒程,有一個位于http://localhost:8080的資源namespace-example鸠天,返回如下的XML:

{
    "description":"返回內容是xml",
    "request":{
      "uri":"/getxmlwithnamespace",
      "method":"get"
    },
    "response":{
      "text":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?> <foo xmlns:ns=\"http://localhost/\">\n<bar>sudo </bar>\n<ns:bar>make me a sandwich!</ns:bar>\n</foo>",
      "headers":{
        "Content-Type":"text/xml"
      }
    }
  }

可以然后聲明http://localhost/這個URI并且驗證其響應:

    @Test
    public void testtwelve(){
        given().
                config(RestAssured.config().xmlConfig(xmlConfig().declareNamespace("test", "http://localhost/"))).
                when().
                get("http://localhost:8889/getxmlwithnamespace").
                then().
                body("foo.bar.text()", equalTo("sudo make me a sandwich!")).
                body(":foo.:bar.text()", equalTo("sudo ")).
                body("foo.test:bar.text()", equalTo("make me a sandwich!"));
    }

這個路徑語法遵循Groovy的XmlSlurper語法。注意直到2.6.0的路徑語法都遵循Groovy的XmlSlurper語法帐姻。請看release notes可以獲知2.6.0之前的版本語法是怎樣的稠集。

注:參考《XML的命名空間》了解本代碼

XPath:
您也可以使用x-path來解析XML響應奶段。舉個例子:
moco接口:

  {
    "description":"返回內容是xml,入?yún)㈩愋褪莏son",
    "request":{
      "uri":"/getxmlwithjson",
      "method":"post",
      "json":{
        "firstName":"John",
        "lastName":"Doe"
      }
    },
    "response":{
      "text":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?> <greeting>\n<firstName>John</firstName>\n<lastName>Doe</lastName>\n</greeting>",
      "headers":{
        "Content-Type":"text/xml"
      }
    }
  }

驗證方法:

        Map map = new HashMap();
        map.put("firstName","John");
        map.put("lastName","Doe");


        given()
                .proxy(8888)
                .body(map)
                .when()
                .post("http://localhost:8889/getxmlwithjson")
                .then()
                .body(hasXPath("/greeting/firstName[text()='John']"));

或者:

        given()
                .proxy(8888)
                .body(map)
                .when()
                .post("http://localhost:8889/getxmlwithjson")
                .then()
                .body(hasXPath("/greeting/firstName",containsString("Jo")));

在XPath表達式中使用命名空間剥纷,你需要在配置中啟用這些選項:
xml:

<h:table xmlns:h="http://www.w3.org/TR/html4/">
   <h:tr>
   <h:td>Apples</h:td>
   <h:td>Bananas</h:td>
   </h:tr>
</h:table>

代碼如下:此代碼運行不成功痹籍,namespaceContext的實例寫的不對。

    @Test
    public void testfourteen(){

        NamespaceContext namespaceContext = new NamespaceContext() {
            @Override
            public String getNamespaceURI(String prefix) {
                return null;
            }

            @Override
            public String getPrefix(String namespaceURI) {
                return null;
            }

            @Override
            public Iterator getPrefixes(String namespaceURI) {
                return null;
            }
        };


        given()
                .config(RestAssured.config().xmlConfig(xmlConfig().with().namespaceAware(true)))
                .proxy(8888)
                .when()
                .get("http://localhost:8889/getxmlwithnamespacetwo")
                .then()
                .body(hasXPath("/h:table",namespaceContext,equalTo("111")));



    }

Schema和DTD
XML響應體也可以驗證為一個XML Schema (XSD)或DTD.

校驗XSD是指:接口中返回xml響應體晦鞋,針對xml生成xml schema蹲缠,就是xsd后綴的文件,校驗xsd文件和返回的xml響應體是否一致悠垛。

校驗DTD是指:接口中返回的xml響應體中定義了DTD的文檔規(guī)范线定,DTD文檔是以dtd后綴的文件,校驗dtd文件和返回的xml響應體的文檔規(guī)范是否一致鼎文。
DTD文檔是指在xml頭中定義的DOCTYPE規(guī)范渔肩,比如下面的D:\Springboot\AutoTest\Chapter15\src\main\resources\XSD\mybatis-3-config.dtd路徑下的mybatis-3-config.dtd文件就規(guī)范了該xml的文檔規(guī)范。

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "D:\Springboot\AutoTest\Chapter15\src\main\resources\XSD\mybatis-3-config.dtd">

XSD 例子

get("/carRecords").then().assertThat().body(matchesXsd(xsd));

xsd是xml schema definition拇惋,xml文檔的結構定義周偎。
moco的接口返回xml文檔,對xml文檔生成對應的xsd文檔

  {
    "description":"模擬返回內容是文件",
    "request" :
    {
      "uri":"/getresponsewithfile",
      "method":"get"
    },
    "response" :
    {
      "file" : "D:/Springboot/AutoTest/Chapter15/src/main/resources/XSD/assertxml.xml"
    }
  }

xml文檔內容如下:


image.png
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <mail mailName="郵件客戶端" mailDescription="打開本地郵件客戶端發(fā)送郵件" >
        <mailServer sp="163" >
            <pop3 key="ip" value="192.168.1.1" />
            <pop3 key="port" value="1234" />
            <user key="userName" value="abcduser" />
            <user key="password" value="dfdf" />
        </mailServer>
    </mail>
</root>

生成的xsd文檔內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="mail"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="mail">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="mailServer"/>
            </xs:sequence>
            <xs:attribute name="mailDescription" use="required" type="xs:NCName"/>
            <xs:attribute name="mailName" use="required" type="xs:NCName"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="mailServer">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" ref="pop3"/>
                <xs:element maxOccurs="unbounded" ref="user"/>
            </xs:sequence>
            <xs:attribute name="sp" use="required" type="xs:integer"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="pop3">
        <xs:complexType>
            <xs:attribute name="key" use="required" type="xs:NCName"/>
            <xs:attribute name="value" use="required" type="xs:NMTOKEN"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="user">
        <xs:complexType>
            <xs:attribute name="key" use="required" type="xs:NCName"/>
            <xs:attribute name="value" use="required" type="xs:NCName"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

對應的測試代碼中這些寫:

 File file = new File("D:\\Springboot\\AutoTest\\Chapter15\\src\\main\\resources\\XSD\\assertxsd.xsd");

        given()
                .proxy(8888)
                .when()
                .get("http://localhost:8889/getresponsewithfile")
                .then()
                .assertThat()
                .body(matchesXsd(file));//接口返回內容是xml撑帖,需要把xml轉換成xml schema蓉坎,然后生成一個文件,把文件傳過來作為參數(shù)

DTD 例子

get("/videos").then().assertThat().body(matchesDtd(dtd));

moco的接口:

  {
    "description":"模擬返回內容是文件",
    "request" :
    {
      "uri":"/getresponsewithDTDfile",
      "method":"get"
    },
    "response" :
    {
      "file" : "D:/Springboot/AutoTest/Chapter15/src/main/resources/databaseConfig.xml"
    }
  }

接口返回的文件頭中內容是:


image.png

我們需要把http://mybatis.org/dtd/mybatis-3-config.dtd 文件下到本地,在瀏覽器中輸入該地址就能下載到文件
測試代碼:

        File file1 = new File("D:\\Springboot\\AutoTest\\Chapter15\\src\\main\\resources\\XSD\\mybatis-3-config.dtd");
        given()
                .proxy(8888)
                .when()
                .get("http://localhost:8889/getresponsewithDTDfile")
                .then()
                .assertThat()
                .body(matchesDtd(file1));//需要傳DTD的文件的地址

matchesXsdmatchesDtd方法在Hamcrest matchers里胡嘿,你可以從io.restassured.matcher.RestAssuredMatchers
導入蛉艾。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市衷敌,隨后出現(xiàn)的幾起案子勿侯,更是在濱河造成了極大的恐慌,老刑警劉巖缴罗,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件助琐,死亡現(xiàn)場離奇詭異,居然都是意外死亡面氓,警方通過查閱死者的電腦和手機兵钮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舌界,“玉大人掘譬,你說我怎么就攤上這事∩氚瑁” “怎么了葱轩?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我靴拱,道長复亏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任缭嫡,我火速辦了婚禮,結果婚禮上抬闷,老公的妹妹穿的比我還像新娘妇蛀。我一直安慰自己,他們只是感情好笤成,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布评架。 她就那樣靜靜地躺著,像睡著了一般炕泳。 火紅的嫁衣襯著肌膚如雪纵诞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天培遵,我揣著相機與錄音浙芙,去河邊找鬼。 笑死籽腕,一個胖子當著我的面吹牛嗡呼,可吹牛的內容都是我干的。 我是一名探鬼主播皇耗,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼南窗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了郎楼?” 一聲冷哼從身側響起万伤,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呜袁,沒想到半個月后敌买,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡傅寡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年放妈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荐操。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡芜抒,死狀恐怖,靈堂內的尸體忽然破棺而出托启,到底是詐尸還是另有隱情宅倒,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布屯耸,位于F島的核電站拐迁,受9級特大地震影響蹭劈,放射性物質發(fā)生泄漏。R本人自食惡果不足惜线召,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一铺韧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缓淹,春花似錦哈打、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至伏蚊,卻和暖如春立轧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背躏吊。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工氛改, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人颜阐。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓平窘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親凳怨。 傳聞我的和親對象是個殘疾皇子瑰艘,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內容