Trong bài viết trước, chúng ta đã học cách cài đặt môi trường cho NUnit project. Trong bài viết này, chúng ta sẽ viết test đầu tiên trong .NET/C#.

Chuẩn bị

Chúng ta có hai project: CustomerOrderService là một library class, và CustomerOrderService.Tests là một NUnit test project.

Đầu tiên hãy tạo hai class Customer và Order, một enum CustomerType trong project CustomerOrderService.

//CustomerType.cs
namespace CustomerOrderService
{
    public enum CustomerType
    {
        Basic,
        Premium,
        SpecialCustomer
    }
}
 
//Customer.cs
namespace CustomerOrderService
{
    public class Customer
    {
        public int CustomerId { get; set; }
        public string CustomerName { get; set; }
        public CustomerType CustomerType { get; set; }
    }
}
 
//Order.cs
namespace CustomerOrderService
{
    public class Order
    {
        public int OrderId { get; set; }
        public int ProductId { get; set; }
        public int ProductQuantity { get; set; }
        public decimal Amount { get; set; }
    }
}

Enum CustomerType được sử dụng để phân biệt các khách hàng. Một vài khách hàng thuộc loại Basic, một số khác lại thuộc Premium hoặc SpecialCustomer.

Class tiếp theo có tên CustomerOrderService được thêm vào business logic là việc giảm giá cho các khách hàng thuộc loại Premium hoặc SpecialCustomer. Như vậy, trong NUnit test project, chúng ta sẽ viết unit test để kiểm tra logic giảm giá có đúng không.

namespace CustomerOrderService
{
    public class CustomerOrderService
    {
        public void ApplyDiscount(Customer customer, Order order)
        {
            if (customer.CustomerType == CustomerType.Premium)
            {
                order.Amount = order.Amount - ((order.Amount * 10) / 100);
            }
            else if(customer.CustomerType == CustomerType.SpecialCustomer)
            {
                order.Amount = order.Amount - ((order.Amount * 20) / 100);
            }
        }
    }
}

Trong method ApplyDiscount ở trên, chúng ta sẽ giảm giá 10% cho các khách hàng Premium và 20% cho SpecialCustomer. Đối với khách hàng thuộc loại Basic, rất tiếc là chúng ta không có chương trình giảm giá cho họ.

Trong project CustomerOrderService.Tests, tạo một class mới có tên CustomerOrderServiceTests.

Thêm attribute TestFixture cho class CustomerOrderServiceTests. Attribute TestFixture sẽ dùng để đánh dấu class có chứa các test method. Và chỉ class nào có attribute TestFixture mới có thể thêm các method test method.

using NUnit.Framework;
 
namespace CustomerOrderService.Tests
{
    [TestFixture]
    public class CustomerOrderServiceTests
    {
    }
}

Thêm một method mới When_PremiumCustomer_Expect_10PercentDiscount và thêm attribute TestCase (hoặc attribute Test).

using NUnit.Framework;
 
namespace CustomerOrderService.Tests
{
    [TestFixture]
    public class CustomerOrderServiceTests
    {
        [TestCase]
        public void When_PremiumCustomer_Expect_10PercentDiscount()
        {
 
        }
    }
}

Mọi test method đều phải có modifier là public và kiểu trả về là void do các test không nên trả về giá trị nào.

Tên test method được đặt theo quy tắc nhất định. Dưới đây là quy tắc mà tôi đã sử dụng trong ví dụ trên.

When_StateUnderTest_Expect_ExpectedBehavior

Phần thứ nhất luôn cố định với When. Phần thứ hai chỉ rõ trạng thái muốn test. Phần ba cũng cố định với Expect và phần thứ tư là hành vi mong đợi của method được test.

Bây giờ chúng ta sẽ viết một trường hợp test đầu tiên. Phần thân test được chia ra làm ba phần AAA.

AAA là viết tắt của Arrange, ActAssert.

Arrange: trong phần Arrange, chúng ta sẽ khởi tạo mọi thức cần thiết để chạy test. Nó bao gồm các dependency và data cần thiết.

Act: trong phần Act, chúng ta gọi method có business logic mafchungs ta muốn test hành vi của nó.

Assert: chỉ rõ điều kiện để test có thể pass. Nếu đáp ứng đủ các điều kiện này, trường hợp test đó là pass, ngược lại test fail.

Ví dụ đầu tiên

[TestCase]
public void When_PremiumCustomer_Expect_10PercentDiscount()
{
    //Arrange
    Customer premiumCustomer = new Customer
    {
        CustomerId = 1,
        CustomerName = "George",
        CustomerType = CustomerType.Premium
    };
 
    Order order = new Order
    {
        OrderId = 1,
        ProductId = 212,
        ProductQuantity = 1,
        Amount = 150
    };
 
    CustomerOrderService customerOrderService = new CustomerOrderService();
 
    //Act
    customerOrderService.ApplyDiscount(premiumCustomer, order);
 
    //Assert
    Assert.AreEqual(order.Amount, 135);
}

Trong phần Arrange, chúng ta khởi tạo hai biến premiumCustomer và order. Ở dòng tiếp theo, một instance của class CustomerOrderService được tạo.

Phần Act, chúng ta gọi method cần test là ApplyDiscount của class CustomerOrderService với những tham số đã được tạo ở phần Arrange.

Và trong Assert, chúng ta kiểm tra giá trị mong đợi trả về. Số tiền có bằng 135 không vậy?

Class Assert

Assert là một class của NUnit framework, nó có các static method để xác nhận các hành vi mong đợi. Đối với ví dụ ở trên, method AreEqual  xác nhận hai giá trị có bằng nahu hay không.

Chúng ta sẽ tìm hiểu rõ hơn về class Assert trong những bài viết sau.

Nếu điều kiện trong Assert pass thì test pass, ngược lại test fail.

Bây giờ chúng ta sẽ chạy trường hợp test ở trên.

Các bước:

  1. Build toàn bộ Solution.
  2. Click vào Visual Studio Test Menu > Windows > Test Explorer
  3. Click vào nút Run All.

Sau khi Run All, nếu test method có tên chuyển sang màu xanh thì nó pass, và nếu chuyển sang màu đỏ thì test đó fail.

Dưới đây là kết quả test của chúng ta:

Bây giờ nếu bạn đổi kết quả mong đợi sang 130 và build lại project. Sau khi click Run All, test của chúng ta fail.

[TestCase]
public void When_PremiumCustomer_Expect_10PercentDiscount()
{
    //Arrange
    Customer premiumCustomer = new Customer
    {
        CustomerId = 1,
        CustomerName = "George",
        CustomerType = CustomerType.Premium
    };
 
    Order order = new Order
    {
        OrderId = 1,
        ProductId = 212,
        ProductQuantity = 1,
        Amount = 150
    };
 
    CustomerOrderService customerOrderService = new CustomerOrderService();
 
    //Act
    customerOrderService.ApplyDiscount(premiumCustomer, order);
 
    //Assert
    Assert.AreEqual(order.Amount, 130);
}

Chúng ta vừa tạo test đầu tiên trong .NET/C#. Các attribute của NUnit sẽ được giới thiệu trong các bài tiếp.

Danh sách tất cả bài viết trong series có thể xem tại đây.