簡體   English   中英

為 Web Api in.Net 編寫單元測試用例

[英]Writing Unit Test cases for Web Api in .Net

我想為 my.Net 項目編寫單元測試用例。 這就是我的 Controller 的樣子

using backend.Models;
using backend.services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace backend.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class GuestTypeController : ControllerBase
    {
        private readonly GuestTypeService _guestType;
        public GuestTypeController(GuestTypeService _guestType)
        {
            this._guestType = _guestType;

        }
        [HttpGet("GuestType")]

        
         public List<GuestType> guestType()
        {

            return _guestType.getGuestType();
        }
    }
}


這就是服務 class 的樣子


namespace backend.services
{
    public class GuestTypeService
    {
        private readonly bookingengineContext dbContext;
        public GuestTypeService(bookingengineContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public List<GuestType> getGuestType()
        {
              
            return dbContext.GuestTypes.ToList();
        }
    }
}

我的 controller 的構造函數中有 object 服務。 在編寫測試用例時,我將我的 controller 和 mocking 稱為我的數據庫上下文和服務 class。 但由於我的 controller 在構造函數中包含服務 class object 我無法對其進行測試。 測試我的控制器的方法是什么。 這是我第一次寫單元測試。 所以我很掙扎。

這樣測試實際上更容易 您可以創建所需的 object 實例。 您甚至不必模擬 DbContext。 您可以在 memory 模式下創建一個針對內存提供程序或 SQLite 的提供程序。 EF Core 文檔有一個部分解釋了可用的測試選項,包括test doubles的各種選項。

存儲庫,或者至少是接口

Repository 選項並不意味着使用完整的 CRUD 方法創建名為IRepository的接口。 這意味着抽象實際的數據訪問,允許它在不修改程序的rest的情況下進行更改。 在這種情況下,您的服務正在這樣做。 如果服務實現了一個接口,您可以模擬它或創建虛擬測試服務:

public interface IGuestTypeService
{
    List<GuestType> GetGuestTypes();
}

public GuestTypeService:IGuestTypeService
{
    ...
    public List<GuestType> GetGuestTypes()
    {
        ....
    }
}

該服務應通過其接口注冊:

serviced.AddScoped<IGuestTypeService,GuestTypeService>();

並且容器應該接受接口

public class GuestTypeController : ControllerBase
{
    private readonly IGuestTypeService _guestType;
    public GuestTypeController(IGuestTypeService _guestType)
    {
        this._guestType = _guestType;
    }

在您的測試中,您可以創建一個虛擬測試服務:

class DummyService:IGuestService
{
    public List<GuestType> GuestTypes{get;set;}

    public List<GuestType> GetGuestType()=>GuestTypes;
}


[Fact]
public void MyTest()
{
    var guestTypes=new List<GuestType>{ ....};
    var service=new DummyService {GuestTypes = guestTypes};

    var controller=new GuestTypeController(service);

    var actual=controller.getGuestType();

    Assert.Equal(actual,guestTypes);
}

測試 DbContext

也可以在內存模式或 memory 集合中創建由 SQLite 支持的 DbContext。 SQLite 提供完整的 SQL 支持,而內存提供程序本質上是一個包裝列表,並在復雜操作中分解。

SQLite 內存部分中解釋了使用 SQLite 進行的測試。

在這種情況下,測試會創建並加載 DbContext 並將其注入到實際服務中:

public class MyTestClass:IDisposable
{
    SQLiteConnection _connection;
    DbContextOptions<bookingengineContext> _contextOptions;

    public MyTestClass()
    {
        // Create and open a connection. This creates the SQLite in-memory database, which will persist until the connection is closed
        // at the end of the test (see Dispose below).
        _connection = new SqliteConnection("Filename=:memory:");
        _connection.Open();

        // These options will be used by the context instances in this test suite, including the connection opened above.
        _contextOptions = new DbContextOptionsBuilder<bookingengineContext>()
            .UseSqlite(_connection)
            .Options;

        SeedData();
    }


 
    public void Dispose() => _connection.Dispose();

    bookingengineContext CreateContext() => new bookingengineContext(_contextOptions);

測試數據通過SeedData()插入數據庫

void SeedData()
{
    var data=new[]
    {
        new GuestType { ... },
        new GuestType { ... }
    };

    using var context = new bookingengineContext(_contextOptions);
    context.Database.EnsureCreated();
    context.AddRange(data);
    context.SaveChanges();
}

測試可以根據需要在內存數據庫之上創建一個新的 DbContext。 實際測試與之前的測試並沒有什么不同

[Fact]
public void MyTest()
{
    using var db=CreateContext();
    var service=new GuestTypeService(db);

    var controller=new GuestTypeController(service);

    var actual=controller.getGuestType();

    var expected=db.GuestTypes.ToList();

    Assert.Equal(actual,expected);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM