Skip to content
  • iImagine
  • Register
  • Log In

Web Development School

Learning made easy.

  • Books
    • Beginning Web Development with ASP.Net Core & Client-Side Technologies
      • TOC
      • Part 1
        • Chapter 1: Static HTML – Designing the landing page
      • Part 2
        • Chapter 2: ASP.Net Core – Let’s talk Dynamic
        • Chapter 3: Introduction to ASP.Net Core MVC
          [ASP.Net Core v9]
      • Part 4
        • Chapter 7: Using Server Side & Client Side technologies together
          [ASP.Net Core v7 & Angular 15]
  • Environment Setup
    • Installing Angular
    • Installing Visual Studio 2022
    • Installing SQL Server 2022 Express
    • Installing Postman
    • Installing Git for Windows
  • Blog
  • iImagine WebSolutions
  • Events
  • Learning Videos
  • Toggle search form

Unit Tests: Search by category

In this module we will unit test the new Search Feature. We have only implemented searching by category (or vehilceType) for now. So that is the only field we need to unit test searching capability for at this point. But we will still need to test both the ApiResult class and VehiclesController class for completeness.

Note: The pathway I am using for development in this module is: C:\Development\FredsCars\FullStack\Module32.
Table Of Contents
  1. Unit Test the ApiResult class
  2. Unit Test the Vehicles controller
  3. Re-run all Unit Tests
  4. What's Next

Unit Test the ApiResult class

Open the ApiResultTests.cs file and modify the code with the changes shown below in bold blue font.

FredsCarsAPI.Tests/Data/ApiResultTests.cs

using FredsCarsAPI.Data;
using MockQueryable.Moq;

namespace FredsCarsAPI.Tests.Data
{
    public class TestPageData
    {
        public int Id { get; set; }
        public string Name { get; set; } = string.Empty;
    }

    public class ApiResultTests
    {
        private List<TestPageData> _data = new List<TestPageData>()
        {
            new TestPageData { Id = 1, Name = "Sam",  },
            new TestPageData { Id = 2, Name = "George" },
            new TestPageData { Id = 3, Name = "Scott" },
            new TestPageData { Id =4, Name = "James" },
            new TestPageData { Id =5, Name = "Melissa" },
            new TestPageData { Id =6, Name = "Ferris" },
            new TestPageData { Id =7, Name = "Debrah" },
            new TestPageData { Id =8, Name = "John" },
            new TestPageData { Id =9, Name = "Greg" },
            new TestPageData { Id =10, Name = "Sarah" },
            new TestPageData { Id = 11, Name = "Mike" },
            new TestPageData { Id = 12, Name = "Larry" },
            new TestPageData { Id = 13, Name = "Emily" },
            new TestPageData { Id = 14, Name = "Jane" }
        };
        
        /*** existing code ***/
        
	#region search tests
	[Fact]
	public async Task CanSearchByCategory()
	{
		// Arrange
		// 1- Create the mock DbSet from the test data
		var dataDbSet = _data.AsQueryable().BuildMockDbSet();
		// 2- Convert the DbSet to an IQueryable interface
		var dataIQueryable = dataDbSet.Object.AsQueryable();

		// Act
		var response = await ApiResult<TestPageData>.CreatAsync(
				dataIQueryable, 0, 4, "Name", "asc", null, null,
					"name", "George,Scott");

		// Assert
		Assert.Equal(2, response.Data.Count);
		Assert.True(response.Data[0].Id == 2
			&& response.Data[0].Name == "George"
			&& response.Data[1].Id == 3
			&& response.Data[1].Name == "Scott");
	}
	#endregion

    }
}

The code above adds a new unit test called CanSearchByCategory().

The arrange and act sections are similar to the earlier unit tests. But, in the act section we null out the two filter parameters and and in parameters to search by the name property in our test data and look for George and Scott.

We then assert that there should be two objects in the result and that the first object is for George and the second object is for Scott.

Unit Test the Vehicles controller

Open the VehiclesControllerTests.cs file and make the code modifications shown below in bold blue font.

FredsCarsAPI.Tests/Controllers/VehiclesControllerTests.cs

using Moq;
using MockQueryable.Moq;
using FredsCarsAPI.Controllers;
using FredsCarsAPI.Repositories;
using FredsCarsAPI.Models;
using FredsCarsAPI.Models.DTOs;
using FredsCarsAPI.Data;

namespace FredsCarsAPI.Tests.Controllers
{
    public class VehiclesControllerTests
    {
        private List<Vehicle> _testData =
            new List<Vehicle>
            {
                new Vehicle { Id = 1,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M1",
                    Model = "M1",
                    Color = "C1",
                    Price = 64000,
                    VIN = "123",
                    VehicleTypeId = 1,
                    VehicleType = new VehicleType { Id = 1, Name = "Car" } 
                },
                new Vehicle { Id = 2,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M2",
                    Model = "M2",
                    Color = "C2",
                    Price = 64000,
                    VIN = "456",
                    VehicleTypeId = 2,
                    VehicleType = new VehicleType { Id = 2, Name = "Truck" }
                },
                new Vehicle { Id = 3,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M3",
                    Model = "M3",
                    Color = "C3",
                    Price = 64000,
                    VIN = "789",
                    VehicleTypeId = 3,
                    VehicleType = new VehicleType { Id = 3, Name = "Jeep" }
                },
                new Vehicle { Id = 4,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M4",
                    Model = "M4",
                    Color = "C4",
                    Price = 64000,
                    VIN = "012",
                    VehicleTypeId = 1,
                    VehicleType = new VehicleType { Id = 1, Name = "Car" }
                },
                new Vehicle { Id = 5,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M5",
                    Model = "M5",
                    Color = "C5",
                    Price = 64000,
                    VIN = "345",
                    VehicleTypeId = 2,
                    VehicleType = new VehicleType { Id = 2, Name = "Truck" }
                },
                new Vehicle { Id = 6,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M6",
                    Model = "M6",
                    Color = "C6",
                    Price = 64000,
                    VIN = "678",
                    VehicleTypeId = 3,
                    VehicleType = new VehicleType { Id = 3, Name = "Jeep" }
                },
                new Vehicle { Id = 7,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M7",
                    Model = "M7",
                    Color = "C7",
                    Price = 64000,
                    VIN = "901",
                    VehicleTypeId = 1,
                    VehicleType = new VehicleType { Id = 1, Name = "Car" }
                },
                new Vehicle { Id = 8,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M8",
                    Model = "M8",
                    Color = "C8",
                    Price = 64000,
                    VIN = "234",
                    VehicleTypeId = 2,
                    VehicleType = new VehicleType { Id = 2, Name = "Truck" }
                },
                new Vehicle { Id = 9,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M9",
                    Model = "M9",
                    Color = "C9",
                    Price = 64000,
                    VIN = "567",
                    VehicleTypeId = 3,
                    VehicleType = new VehicleType { Id = 3, Name = "Jeep" }
                },
                new Vehicle { Id = 10,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M10",
                    Model = "M10",
                    Color = "C10",
                    Price = 64000,
                    VIN = "890",
                    VehicleTypeId = 1,
                    VehicleType = new VehicleType { Id = 1, Name = "Car" }
                },
                new Vehicle { Id = 11,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M11",
                    Model = "M11",
                    Color = "C11",
                    Price = 64000,
                    VIN = "abc",
                    VehicleTypeId = 2,
                    VehicleType = new VehicleType { Id = 2, Name = "Truck" }
                },
                new Vehicle { Id = 12,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M12",
                    Model = "M12",
                    Color = "C12",
                    Price = 64000,
                    VIN = "def",
                    VehicleTypeId = 3,
                    VehicleType = new VehicleType { Id = 3, Name = "Jeep" }
                },
                new Vehicle { Id = 13,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M13",
                    Model = "M13",
                    Color = "C13",
                    Price = 64000,
                    VIN = "ghi",
                    VehicleTypeId = 1,
                    VehicleType = new VehicleType { Id = 1, Name = "Car" }
                },
                new Vehicle { Id = 14,
                    Status = Status.New,
                    Year = "2022",
                    Make = "M14",
                    Model = "M14",
                    Color = "C14",
                    Price = 64000,
                    VIN = "jkl",
                    VehicleTypeId = 2,
                    VehicleType = new VehicleType { Id = 2, Name = "Truck" }
                },
            };

        /*** existing code ***/

        #region Search Tests
        [Fact]
        public async Task CanSearchByCategory()
        {
            // Arrange
            // Create the mock from the test data
            Mock<IVehicleRepository> mockVehicleRepo =
                new Mock<IVehicleRepository>();

            var mockVehicleIQueryable =
                _testData.AsQueryable().BuildMock();
            mockVehicleRepo.Setup(m => m.Vehicles).Returns(mockVehicleIQueryable);

            var controller = new VehiclesController(mockVehicleRepo.Object);

            // Act
            ApiResult<VehicleDTO> result =
                await controller.GetVehicles(searchColumns: "Color",
                searchValues: "C3,C5,C16");

            Assert.Equal(2, result.Data.Count());
        }
        #endregion
    }
}

The code above is again similar to the build up of the other vehicles controller unit tests so far in the arrange and act sections. But, in the act section this time we change the filter named parameters to the search named parameters in the call to the controller’s GetVehicles() method. We search by the Color property of the VehicleDTO test data for the values C3, C5, and C16. Then we assert that we should get back two objects. We get back the two matching objects for C3 and C5 but our test data does not have an object with Color set to C16. So we get back two objects rather than three in the response.

Re-run all Unit Tests

Let’s go ahead and run a dotnet test command from the command line to make sure the two new unit tests pass along with all the others. And, that our new code hasn’t broken any of the other tests.

dotnet test

In the screenshot above you can see that everything has passes. Fourteen tests passed and zero tests failed.

What’s Next

Well we have finally wrapped up the main Vehicles page where a user can see a list of Vehicles, filter the results or search by category, page through the results and sort the results. We sure put a lot of work into this one page. We probably could have made all of this work in a lot fewer modules if we just forgot about a generic ApiResult and threw all of the logic into the controller and used tenacity and elbow grease to get it done.

But instead we concentrated on our architecture and used proven design patterns to keep our code DRY, maintainable, and scalable.

Shortly we will start to get into Forms and design our edit and details pages as promised. But first, something still doesn’t seem quite right with our loading spinner. Sometimes it doesn’t seem to go away and get replaced with our table results and pager controls once we see that the data results have indeed come back from logging in the ASP.Net Core development console hosting the application.

Let’s make another pit stop and try to get this working once and for all.

< Prev
Next >

Leave a ReplyCancel reply

Chapter 1: Static HTML – Designing the landing page.

  • Static HTML – Designing the landing page.
  • Let’s get started!
  • Mock your site with HTML
  • Make CSS easy with Bootstrap
  • Mock your content
  • Introducing JavaScript
  • JavaScript Code Improvements
  • Results Data
  • Images and the HTML Image Element.
  • Revisiting Reusability for CSS and JavaScript
  • Reuse for HTML: PART 1
  • Reuse for HTML: PART 2
  • Details Page – Using a Bootstrap Component
  • Creating Links
  • Chapter One Conclusion

Chapter 2: ASP.Net Core – Let’s talk Dynamic

  • Introduction to ASP.Net Core
  • What is .Net?
  • What is ASP.Net
  • Introduction to Entity Framework Core

Chapter 3: ASP.Net MVC Core – Models, Views, and Controllers [ASP.Net Core v9]

  • Introduction to ASP.Net Core MVC
  • Create the project: ASP.Net Core MVC
  • Explore the ASP.Net Core Empty Web Project Template
  • Configure the Application for MVC
  • Create a Controller: Home Controller
  • Create a View: Index View for the Home Controller
  • Install Bootstrap using Libman
  • Create the Layout template
  • Create the Model
  • Install EF Core & Create the Database
  • Seed the Database: Loading test data
  • DI (Dependency Injection): Display a List of Vehicles
  • Repository Pattern: The Vehicles Repo
  • Unit Test 1: Home Controller Can Use Vehicle Repository
  • Unit Test 2: Vehicle Repository Can Return List
  • Add the ImagePath Migration and Thumbnail images to results
  • Pagination: Create a Custom Tag Helper
  • Sorting
  • Category Filter
  • Partial View: Break out the vehicle results
  • View Component: Create dynamic category buttons
  • Create the Details page
  • Create the Create Page

Chapter 7: Using Server Side & Client Side technologies together. [ASP.Net Core v7 & Angular v15]

  • Intro to Full Stack Development
  • Fred’s Cars – Full Stack Development
  • Prepare the environment
  • Create the Visual Studio Solution
  • Add the ASP.Net Core Web API project
  • Add the Angular Project
  • Wire it up!
  • WeatherForecast: Understanding the basics
  • Vehicles API Controller: Mock Data
  • Vehicles Angular Component: Consuming Data
  • Routing and Navigation
  • Using a Component Library: Angular Material
  • Our first Angular Material Component: MatToolbar
  • Configuring for Saas: CSS with superpowers
  • Create the Header & Footer components
  • Displaying Results with MatTable
  • Loading: Using a Progress Spinner
  • MatTable: Client-Side Paging and Sorting
  • MatSidenav: Create a Search Sidebar
  • MatCheckbox: Category Search UI
  • Adding an image to the welcome page
  • Create the database with Entity Framework Core migrations
  • MatPaginator & PageEvent: Custom Server-Side Paging
  • Unit Testing: Custom Server-Side Paging
  • Repository Pattern: VehicleRepository
  • Unit Test: Paging in the Vehicles controller
  • Server-Side Sorting
  • Unit Tests: Sorting
  • Filter (Quick Search)
  • Unit Tests: Filter feature
  • Advanced Search: Categories
  • Unit Tests: Search by category
  • Progress Spinner: Final Fix

TOC

  • What were WebForms?
  • Enter MVC
    • Understanding MVC
    • Advantages of MVC
  • ASP.Net Core MVC – A total rewrite
  • ASP.Net Core 2 MVC – Here come Razor Pages
    • Understanding Razor Pages
  • ASP.Net Core 3 – Dropping the MVC reference
    • Understanding Blazor
  • Dropping the MVC reference
  • Hello .Net 5!
  • What’s Next? – Here comes .Net 6.

Recent Posts

  • Angular Commands Cheat Sheet
  • Installing Git for Windows
  • Installing Postman
  • Installing SQL Server 2022 Express
  • Installing Visual Studio 2022

Recent Comments

No comments to show.

Archives

  • November 2023
  • October 2023
  • June 2023
  • October 2021

Categories

  • Angular
  • ASP.Net
  • Environment Setup
  • See All
  • SQL Server
  • Visual Studio
  • Web API & Rest Services

WordPress Theme Editor

Copyright © 2025 Web Development School.

Powered by PressBook Blog WordPress theme