如何在Visual Studio中编写Web API的测试代码?

How to write test code for Web API in Visual Studio?

我对测试项目有点陌生。我目前有一个 Web api 项目,其中包含 Get、Put、Post 和 Delete 方法。在编写测试用例时,我很困惑。我是否应该编写测试代码来测试 Http URL?

我的网站api代码:

    // GET api/values/5
    [HttpGet("{id}")]
    public IActionResult Get(string id)
    {
        using (var unitOfWork = new UnitOfWork(_db))
        {
            var r = unitOfWork.Resources.Get(id);

            unitOfWork.Complete();

            Models.resource result = ConvertResourceFromCoreToApi(r);

            if (result == null)
            {
                return NotFound();
            }
            else
            {
                return Ok(result);
            }
        }
    }

在我的测试项目中,我有点卡在这里。我们正在使用 Xunit。如何编写测试代码来测试Get方法?或者我应该编写代码来测试 URL api/values/5,但是如何呢?

    [Fact]
    public void GetTest()
    {
        using (var unitOfWork = new UnitOfWork(new MockDatabase()))
        {

        }
    }

如有任何帮助,我们将不胜感激。

您需要对控制器进行一些设计更改以使其易于测试。在您的操作中,您正在创建一个实例,这将使使用对控制器的虚假依赖项进行测试变得困难。此外,您的控制器应该依赖于抽象而不是具体化,这将使控制器更易于测试。

public class MyWebApiController : ApiController {
    private IUnitOfWork unitOfWork;

    public MyWebApiController(IUnitOfWork unitOfWork) {
       this.unitOfWork = unitOfWork;
    }

    // GET api/values/5
    [HttpGet("{id}")]
    public IActionResult Get(string id) {        
        var r = unitOfWork.Resources.Get(id);

        unitOfWork.Complete();

        Models.resource result = ConvertResourceFromCoreToApi(r);

        if (result == null) {
            return NotFound();
        } else {
            return Ok(result);
        }        
    }

    //...other code
}

注意控制器使用依赖注入来注入 IUnitOfWork。这使控制器更易于测试,因为您可以在单元测试时注入其依赖项的模拟。

从那里只是创建控制器的实例并使用依赖项的模拟调用被测方法。

[Fact]
public void GetTest() {
    //Arrange (Setup the parts needed to run test)
    var unitOfWork = new MockUnitOfWork(new MockDatabase());

    //Or using your mocking framework of choice
    //var unitOfWork = Mock.Of<IUnitOfWork>(); //this is using Moq

    var controller = new MyWebApiController(unitOfWork);
    var id = "Test Id value here";

    //Act (call the method under test)
    var result - controller.Get(id);

    //Assert (check results)
    //...Do your assertion pertaining to result of calling method under test
}

参考:Unit Testing Controllers in ASP.NET Web API 2

在真正对控制器进行单元测试之前,您需要进行一些更改。您需要将 UnitOfWork class 的实例传递到控制器的构造函数中。然后你的控制器方法代码变成:

// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(string id)
{    
    var r = unitOfWork.Resources.Get(id);

    unitOfWork.Complete();

    Models.resource result = ConvertResourceFromCoreToApi(r);

    if (result == null)
    {
        return NotFound();
    }
    else
    {
        return Ok(result);
    }

然后在你的单元测试中你这样做:

[Fact]
public void GetTest()
{
    // Arrange
    // You really want to mock your unit of work so you can determine
    // what you are going to send back
    var unitOfWork = new MockUnitOfWork();
    var systemUnderTest = new Controller(unitOfWork);
    system.Request = new HttpRequestMessage();

    // Act
    var result = systemUnderTest.Get(1);

    // Assert
    // Here you need to verify that you got back the expected result
}

将 UnitOfWork class 注入控制器可能是另一个问题。 Mark Seemann 在这个问题上有出色的 post,但可能有点高级。有许多不同的方法可以用更简单的方法(但可能不是那么健壮的方法)来实现这一点。 Google 是你的朋友。但是如果你有问题,post另一个问题。

希望对您有所帮助。