• Blog

Automating NUnit Test Cases with GitHub Copilot Chat

Automating NUnit Test Cases with GitHub Copilot Chat
Table of Contents

Sign Docs 3x Faster

Send, sign, and manage documents securely and efficiently.

When building a project, ensuring its stability through comprehensive test cases is critical. In this blog, we’ll explore how GitHub Copilot Chat can help automate writing test cases, making the development process smoother and more efficient.

Imagine you’re developing a product management system where CRUD (create, read, update, delete) operations are used for managing product details. Now, let’s see how you would write test cases for its methods using GitHub Copilot.

Test case for adding a product

Let’s start by focusing on one of the core operations: adding a product. We’ll walk through how to write a test case for the AddProduct method in ProductController.cs using GitHub Copilot Chat.

After installing GitHub Copilot Chat, open the Copilot Chat prompt and request it to generate a test case. For example, here is the method for adding a product:

   

public IActionResult AddProduct([FromBody] ProductDetails productDetails)
{
    if (this.ModelState.IsValid)
    {
        this._productService.Add(productDetails);
        return this.Ok();
    }
    return this.BadRequest();
}
    

To generate a test case for this method using GitHub Copilot, select the method and type a request in the chat prompt. GitHub Copilot will then provide a test case based on your query. You can see the query I used and the response from the copilot in the following images.

Test-case-for-adding-a-product
   

[Fact]
public void AddProduct_ValidProductDetails_ReturnsOk()
{
    // Arrange
    var options = new DbContextOptionsBuilder()
        .UseInMemoryDatabase(databaseName: "AddProduct_ValidProductDetails_ReturnsOk")
        .Options;
    using (var context = new ProductContext(options))
    {
        var productService = new ProductService(context);
        var controller = new ProductController(null, productService);
        var productDetails = new ProductDetails
        {
            Id = 1,
            Name = "TestProduct",
            Description = "TestDescription",
            Price = 10.0,
            Stock = 100
        };
        // Act
        var result = controller.AddProduct(productDetails);
        // Assert
        Assert.IsType(result);
        Assert.Equal(1, context.Products.Count());
    }
}
[Fact]
public void AddProduct_InvalidProductDetails_ReturnsBadRequest()
{
    // Arrange
    var options = new DbContextOptionsBuilder()
        .UseInMemoryDatabase(databaseName: "AddProduct_InvalidProductDetails_ReturnsBadRequest")
        .Options;
    using (var context = new ProductContext(options))
    {
        var productService = new ProductService(context);
        var controller = new ProductController(null, productService);
        controller.ModelState.AddModelError("Name", "Required");
        var productDetails = new ProductDetails
        {
            Id = 1,
            Description = "TestDescription",
            Price = 10.0,
            Stock = 100
        };
        // Act
        var result = controller.AddProduct(productDetails);
        // Assert
        Assert.IsType(result);
        Assert.Equal(0, context.Products.Count());
    }
}
    

Writing test cases with mocking

Initially, I requested test cases without mocking the service. Now, I’ll ask Copilot to write test cases with mocked services.

Test-cases-with-mocking
   

[Fact]
public void AddProduct_ValidProductDetails_IncreasesCountTwice()
{
    var productServiceMock = new Mock ();
    var productList = new List();
    productServiceMock.Setup(service => service.Add(It.IsAny())).Callback(product =>
    {
        productList.Add(product);
        productList.Add(product);
    });
    var controller = new ProductController(null, productServiceMock.Object);
    var productDetails = new ProductDetails
    {
        Id = 1,
        Name = "TestProduct",
        Description = "TestDescription",
        Price = 10.0,
        Stock = 100
    };
    var result = controller.AddProduct(productDetails);
    Assert.IsType(result);
    Assert.Equal(2, productList.Count);
}
[Fact]
public void AddProduct_InvalidProductDetails_DoesNotIncreaseCount()
{
    var productServiceMock = new Mock();
    var productList = new List();
    var controller = new ProductController(null, productServiceMock.Object);
    controller.ModelState.AddModelError("Name", "Required");
    var productDetails = new ProductDetails
    {
        Id = 1,
        Description = "TestDescription",
        Price = 10.0,
        Stock = 100
    };
    var result = controller.AddProduct(productDetails);
    Assert.IsType(result);
    Assert.Equal(0, productList.Count);
}
    

Model validation

Next, I request that Copilot validate all the properties used in the ProductDetails class. Copilot generates test cases for different types of model validation based on my request.

Model-validation
   

[Fact]
public void AddProduct_MissingRequiredName_ReturnsBadRequest()
{
    var productServiceMock = new Mock();
    var productList = new List();
    var controller = new ProductController(null, productServiceMock.Object);
    controller.ModelState.AddModelError("Name", "Required");
    var productDetails = new ProductDetails
    {
        Id = 1,
        Description = "TestDescription",
        Price = 10.0m,
        Quantity = 10,
        Category = "TestCategory",
        Manufacturer = "TestManufacturer",
        DateAdded = DateTime.Now
    };
    var result = controller.AddProduct(productDetails);
    Assert.IsType(result);
    Assert.Empty(productList);
}
[Fact]
public void AddProduct_NameExceedsMaxLength_ReturnsBadRequest()
{
    var productServiceMock = new Mock();
    var productList = new List();
    var controller = new ProductController(null, productServiceMock.Object);
    controller.ModelState.AddModelError("Name", "Name cannot exceed 50 characters.");
    var productDetails = new ProductDetails
    {
        Id = 1,
        Name = new string('A', 51),
        Description = "TestDescription",
        Price = 10.0m,
        Quantity = 10,
        Category = "TestCategory",
        Manufacturer = "TestManufacturer",
        DateAdded = DateTime.Now
    };
    var result = controller.AddProduct(productDetails);
    Assert.IsType(result);
    Assert.Empty(productList);
}
[Fact]
public void AddProduct_QuantityOutOfRange_ReturnsBadRequest()
{
    var productServiceMock = new Mock();
    var productList = new List();
    var controller = new ProductController(null, productServiceMock.Object);
    controller.ModelState.AddModelError("Quantity", "Quantity must be greater than 0 and less than 100.");
    var productDetails = new ProductDetails
    {
        Id = 1,
        Name = "TestProduct",
        Description = "TestDescription",
        Price = 10.0m,
        Quantity = 101,
        Category = "TestCategory",
        Manufacturer = "TestManufacturer",
        DateAdded = DateTime.Now
    };
    var result = controller.AddProduct(productDetails);
    Assert.IsType(result);
    Assert.Empty(productList);
}
    
Model Validation

[Fact]
public void AddProduct_InvalidProductDetails_ReturnsBadRequest()
{
    var productServiceMock = new Mock();
    var productList = new List();
    var controller = new ProductController(productServiceMock.Object);
    var productDetails = new ProductDetails
    {
        Id = 1,
        Description = "TestDescription",
        Price = 10.0m,
        Quantity = 10,
        Category = "TestCategory",
        Manufacturer = "TestManufacturer",
        DateAdded = DateTime.Now
    };
    controller.TryValidateModel(productDetails);
    var result = controller.AddProduct(productDetails);
    Assert.IsType(result);
    Assert.Empty(productList);
}
    

Writing test cases for all methods

To write test cases for all the methods in the file, simply open the file and enter a request in the Copilot Chat prompt window.

Test-cases-for-all-methods
   

[Fact]
public void AddProduct_ValidProductDetails_ReturnsOk()
{
    var productServiceMock = new Mock();
    var productList = new List();
    productServiceMock.Setup(service => service.Add(It.IsAny())).Callback(product =>
    {
        productList.Add(product);
    });
    var controller = new ProductController(null, productServiceMock.Object);
    var productDetails = new ProductDetails
    {
        Id = 1,
        Name = "TestProduct",
        Description = "TestDescription",
        Price = 10.0m,
        Quantity = 10,
        Category = "TestCategory",
        Manufacturer = "TestManufacturer",
        DateAdded = DateTime.Now
    };
    var result = controller.AddProduct(productDetails);
    Assert.IsType(result);
    Assert.Single(productList);
}
[Fact]
public void AddProduct_InvalidProductDetails_ReturnsBadRequest()
{
    var productServiceMock = new Mock();
    var productList = new List();
    var controller = new ProductController(null, productServiceMock.Object);
    controller.ModelState.AddModelError("Name", "Required");
    var productDetails = new ProductDetails
    {
        Id = 1,
        Description = "TestDescription",
        Price = 10.0m,
        Quantity = 10,
        Category = "TestCategory",
        Manufacturer = "TestManufacturer",
        DateAdded = DateTime.Now
    };
    var result = controller.AddProduct(productDetails);
    Assert.IsType(result);
    Assert.Empty(productList);
}
[Fact]
public void GetProduct_ExistingProduct_ReturnsProductDetails()
{
    var productServiceMock = new Mock();
    var productDetails = new ProductDetails
    {
        Id = 1,
        Name = "TestProduct",
        Description = "TestDescription",
        Price = 10.0m,
        Quantity = 10,
        Category = "TestCategory",
        Manufacturer = "TestManufacturer",
        DateAdded = DateTime.Now
    };
    productServiceMock.Setup(service => service.Get("TestProduct")).Returns(productDetails);
    var controller = new ProductController(null, productServiceMock.Object);
    var result = controller.GetProduct("TestProduct");
    Assert.Equal(productDetails, result);
}
[Fact]
public void GetProduct_NonExistingProduct_ReturnsNull()
{
    var productServiceMock = new Mock();
    productServiceMock.Setup(service => service.Get("NonExistingProduct")).Returns((ProductDetails)null);
    var controller = new ProductController(null, productServiceMock.Object);
    var result = controller.GetProduct("NonExistingProduct");
    Assert.Null(result);
}
[Fact]
public void UpdateProduct_ValidProductDetails_ReturnsOk()
{
    var productServiceMock = new Mock();
    var productDetails = new ProductDetails
    {
        Id = 1,
        Name = "TestProduct",
        Description = "TestDescription",
        Price = 10.0m,
        Quantity = 10,
        Category = "TestCategory",
        Manufacturer = "TestManufacturer",
        DateAdded = DateTime.Now
    };
    var controller = new ProductController(null, productServiceMock.Object);
    var result = controller.UpdateProduct(productDetails);
    Assert.IsType(result);
}
[Fact]
public void UpdateProduct_InvalidProductDetails_ReturnsBadRequest()
{
    var productServiceMock = new Mock();
    var controller = new ProductController(null, productServiceMock.Object);
    controller.ModelState.AddModelError("Name", "Required");
    var productDetails = new ProductDetails
    {
        Id = 1,
        Description = "TestDescription",
        Price = 10.0m,
        Quantity = 10,
        Category = "TestCategory",
        Manufacturer = "TestManufacturer",
        DateAdded = DateTime.Now
    };
    var result = controller.UpdateProduct(productDetails);
    Assert.IsType(result);
}
[Fact]
public void DeleteProduct_ExistingProduct_ReturnsOk()
{
    var productServiceMock = new Mock();
    productServiceMock.Setup(service => service.Remove("TestProduct"));
    var controller = new ProductController(null, productServiceMock.Object);
    var result = controller.DeleteProduct("TestProduct");
    Assert.IsType(result);
}
[Fact]
public void DeleteProduct_NonExistingProduct_ReturnsOk()
{
    var productServiceMock = new Mock();
    productServiceMock.Setup(service => service.Remove("NonExistingProduct"));
    var controller = new ProductController(null, productServiceMock.Object);
    var result = controller.DeleteProduct("NonExistingProduct");
    Assert.IsType(result);
}
    

Conclusion

GitHub Copilot Chat simplifies the process of writing NUnit test cases by automating much of the code generation. Whether you need to write tests with or without mocking or perform model validation, Copilot Chat can assist with these tasks, saving time and effort. This makes it a valuable tool for developers looking to increase productivity while ensuring project quality.

Latest blog posts

Simplify Insurance Authorizations & Billing with Secure eSignatures

Simplify Insurance Authorizations & Billing with Secure eSignatures

Simplify insurance authorizations and billing with secure eSignatures. Speed up approvals, reduce errors, & ensure HIPAA compliance across healthcare workflows.

Webinar Show Notes: Embed eSignature Workflows in .NET App 

Webinar Show Notes: Embed eSignature Workflows in .NET App 

Embed eSignature workflows in your .NET app with BoldSign for a seamless, secure, and branded signing experience. Simplify sending, signing, and tracking.

BulkSend your documents to multiple recipients using BoldSign 

BulkSend your documents to multiple recipients using BoldSign 

Managing high-volume signature requests can be time-consuming, especially when each document needs to be personalized and securely delivered. That’s where the BoldSign bulk send feature becomes invaluable. Instead of manually preparing and sending individual signature requests, bulk send enables you to deliver customized copies of a document to multiple recipients in one streamlined process. Whether […]

Sign up for your free trial today!

  • tick-icon
    30-day free trial
  • tick-icon
    No credit card required
  • tick-icon
    30-day free trial
  • tick-icon
    No credit card required
signup-banner