A new test file

We’ll start by creating a new test file. Let's name this file SpeakerControllerSearchTests.cs. Now, create the first test, ItExists:

[Fact]
public void ItExists()
{
var controller = new SpeakerController();
}

To make this compile, you'll need to create a Web API controller called SpeakerMeetController. Add a new ASP.NET Core Web Application project to your solution. Give your project a name of SpeakerMeet.API and choose the Web API template to get started. Add a reference to this project from your test project and add the appropriate using statement.

Now, let's ensure that there is a Search endpoint available. Let's create another test:

[Fact]
public void ItHasSearch()
{
// Arrange
var controller = new SpeakerController();

// Act
controller.Search("Jos");
}

Make this test pass by creating a Search method that accepts a string.

Let's confirm that the Search action result returns an OkObjectResult:

[Fact]
public void ItReturnsOkObjectResult()
{
// Arrange
var controller = new SpeakerController();

// Act
var result = controller.Search("Jos");

// Assert
Assert.NotNull(result);
Assert.IsType<OkObjectResult>(result);
}

Note the multiple Asserts. While we want to limit our tests to a single Act, sometimes it is acceptable, even necessary, to have multiple Asserts.

Once the ItReturnsOkObjectResult test passes, you should delete the ItExists and ItHasSearch tests. Remember, we want to finish the red, green, refactor cycle and keep our code neat and clean. This includes the test suite, so if you have tests that are no longer valid or add no value, then you should feel free to remove them. You don't want to have to maintain more code than is required. This will help your test suite stay relevant and run nice and fast.

Now, let’s test that the result is a collection of speakers:

[Fact]
public void ItReturnsCollectionOfSpeakers()
{
// Arrange
var controller = new SpeakerController();

// Act
var result = controller.Search("Jos") as OkObjectResult;

// Assert
Assert.NotNull(result);
Assert.NotNull(result.Value);
Assert.IsType<List<Speaker>>(result.Value);
}

We're starting to get a little redundant here. Now is a good time to refactor our tests to make them cleaner. Let's extract the creation of the SpeakerController and initialize this value in the constructor. Be sure to remove the creation in your tests and use this new instance:

private readonly SpeakerController _controller;

public SpeakerControllerSearchTests()
{
_controller = new SpeakerController();
}

Finally, we're ready to start testing the value of the results. Let's write a test entitled GivenExactMatchThenOneSpeakerInCollection:

[Fact]
public void GivenExactMatchThenOneSpeakerInCollection()
{
// Arrange
// Act
var result = _controller.Search("Joshua") as OkObjectResult;

// Assert
var speakers = ((IEnumerable<Speaker>)result.Value).ToList();
Assert.Equal(1, speakers.Count);
}

To get this test to work, we'll need to hard-code some data. Don't worry, we're building this application slowly. The hard-coded data will be removed at a later point:

[Fact]
public void GivenExactMatchThenOneSpeakerInCollection()
{
// Arrange
// Act
var result = _controller.Search("Joshua") as OkObjectResult;

// Assert
var speakers = ((IEnumerable<Speaker>)result.Value).ToList();
Assert.Equal(1, speakers.Count);
Assert.Equal("Joshua", speakers[0].Name);
}

Ensure that our search string is not case-sensitive:

[Theory]
[InlineData("Joshua")]
[InlineData("joshua")]
[InlineData("JoShUa")]
public void GivenCaseInsensitveMatchThenSpeakerInCollection (string searchString)
{
// Arrange
// Act
var result = _controller.Search(searchString) as OkObjectResult;

// Assert
var speakers = ((IEnumerable<Speaker>)result.Value).ToList();
Assert.Equal(1, speakers.Count);
Assert.Equal("Joshua", speakers[0].Name);
}

Next, we need to test to verify that, if the string provided does not match any of our data, then an empty collection is returned:

[Fact]
public void GivenNoMatchThenEmptyCollection()
{
// Arrange
// Act
var result = _controller.Search("ZZZ") as OkObjectResult;

// Assert
var speakers = ((IEnumerable<Speaker>)result.Value).ToList();
Assert.Equal(0, speakers.Count);
}

And finally, we'll test that any speaker that begins with our search string will be returned:

[Fact]
public void Given3MatchThenCollectionWith3Speakers()
{
// Arrange
// Act
var result = _controller.Search("jos") as OkObjectResult;

// Assert
var speakers = ((IEnumerable<Speaker>)result.Value).ToList();
Assert.Equal(3, speakers.Count);
Assert.True(speakers.Any(s => s.Name == "Josh"));
Assert.True(speakers.Any(s => s.Name == "Joshua"));
Assert.True(speakers.Any(s => s.Name == "Joseph"));
}

Here's what the code we came up with looks like. Your implementation may vary somewhat:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;

namespace SpeakerMeet.Api.Controllers
{
[Route("api/[controller]")]
public class SpeakerController : Controller
{
[Route("search")]
public IActionResult Search(string searchString)
{
var hardCodedSpeakers = new List<Speaker>
{
new Speaker{Name = "Josh"},
new Speaker{Name = "Joshua"},
new Speaker{Name = "Joseph"},
new Speaker{Name = "Bill"},
};

var speakers = hardCodedSpeakers.Where(x => x.Name.StartsWith(searchString, StringComparison.OrdinalIgnoreCase)).ToList();

return Ok(speakers);
}
}

public class Speaker
{
public string Name { get; set; }
}
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.229.111