Automated HTTP Testing! Part 2 of 2

In part 1:

  • We created the data structure to hold the Person entity and also  a method to compare two people together.
  • Wrote a method for executing a GET request for a HTTP serivice.
  • Wrote a simple GetPerson test.

In this, the second part, we add an additional GET test as well as add functionality for creating data.

Get All

Sometimes, you may want to test a collection of entities. Json.NET provides the ability to serialize/deserialize collections as well. Let’s add a method to the Person entity class for getting a collection.

        public static IEnumerable<Person> GetPeople()
        {
            return JsonConvert.DeserializeObject<List<Person>>(Api.Get(new Uri(Config.Url + "api/person")));
        }

Next, we’ll use this method in our PersonTests and make some assertions.

        [TestMethod]
        public void GetPeople()
        {
            var people = Person.GetPeople();

            Assert.AreEqual(2, people.Count());
            Assert.IsTrue(people.Any(p => p.Equals(new Person
            {
                FirstName = "Joe",
                LastName = "Schmoe",
                Age = 25,
                Married = false,
                BirthDate = new DateTime(1980, 1, 1)
            })));
            Assert.IsTrue(people.Any(p => p.Equals(new Person
            {
                FirstName = "Jon",
                LastName = "Smith",
                Age = 35,
                Married = true,
                BirthDate = new DateTime(1990, 2, 1)
            })));
        }

Post

The only difference between posting and getting data is, instead of deserializing data that we’ve received from the server, we serialize the data we would like to send to the server.

For example, let’s say we would like to add this person to the system:

{
    "firstName":"Jane",
    "lastName": "Smith",
    "age": 35,
    "married": true,
    "birthDate": "03/01/1990"
}

The first thing we need to add is a Post method to the Api class.

        public static String Post(Uri uri, String payload)
        {
            using (var client = new HttpClient())
            {
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
                request.Content = new StringContent(payload.ToString(), Encoding.UTF8, "application/json");

                HttpResponseMessage response = client.SendAsync(request).Result;
                if (response.IsSuccessStatusCode)
                {
                    return response.Content.ReadAsStringAsync().Result;
                }
                else
                {
                    throw new System.Net.WebException(response.Content.ReadAsStringAsync().Result);
                }
            }
        }

This looks similar to the Get method except it takes two parameters. The second parameter is a string payload. This is what gets sent over the wire and is data the application under test will use to create a Person.

Next, let’s add PostPerson to the Person entity class.

        public static String PostPerson(Person person)
        {
            return Api.Post(new Uri(Config.Url + "api/person"), JsonConvert.SerializeObject(person));
        }

This looks similar to the GetPerson method, but instead of deserializing a person returned from the server, this serializes a person to be sent to the server.

With the pieces in place, we can write a test.

        [TestMethod]
        public void PostPerson()
        {
            var person = new Person
            {
                FirstName = "Jane",
                LastName = "Smith",
                Age = 35,
                Married = true,
                BirthDate = new DateTime(1990, 3, 1)
            };

            var response = Person.PostPerson(person);

            //If we were testing a real application, we would
            //execute a GET here in order to validate the POST
            //was successful.
            //Assert.IsTrue(person.Equals(Person.GetPerson("jane")));

            Assert.AreEqual("Person creation success!", response);
        }

You’ll notice the commented lines above. If we were testing a real application (not a mocked one), we would request the newly created ‘Jane’ by executing GET against http://demo3192753.mockable.io/api/person/jane and comparing the actual result with the expected.

Sad path

What if we wanted to test the error conditions of our application? We can do that too. Check out this test for requesting a person that doesn’t exist.

        [TestMethod]
        public void InvalidPerson()
        {
            try
            {
                var response = Person.GetPerson("sally");
                Assert.Fail("Expected 404 error message.");
            }
            catch (System.Net.WebException e)
            {
                Assert.AreEqual("No person exists with specified name.", e.Message);
            }
        }

We expect the Person request to fail, so if the test makes it past that line of code, we should fail the test. Once the Person request fails, the catch asserts that the error message is equal to the error message we expect.

That’s it for automated HTTP testing (for now). Want to see some different tests or have any issues? Just ask!

Leave a Reply

Your email address will not be published. Required fields are marked *