使用异步WebAPI的替代数据进行单元测试

时间:2018-12-14 15:34:13

标签: unit-testing asp.net-web-api nunit dapper substitution

我正在使用NUnit进行WebAPI的单元测试。要测试的方法是异步的,通常会调用异步一个实现dapper的类来访问数据库。我想用NSubstitute伪造数据。这是API:

public class ModelController : ApiController
{
    public async Task<IHttpActionResult> GetAsync()
    {
        // fake list for testing purposes
        List<MyModel> myModels = new List<MyModel>
        {
            new MyModel
            {
                ID = 1,
                Name = "Test1",
                Created = DateTime.Now,
                Creator = "Admin"
            },
            new MyModel
            {
                ID = 2,
                Name = "Test2",
                Created = DateTime.Now,
                Creator = "Admin"
            }
        };
        return this.Ok(myModels); // <= here would be a call to a class implementing dapper like: return this.Ok(await DbRepo.GetAsync())
    }
}

这是测试:

[TestFixture]
public class ModelControllerTests : ApiController
{
    [Test]
    public async Task GetAsync_GetAll_ReturnOkHttpResultWithListOfMyModels()
    {
        private ModelController target = Substitute.For<ModelController>();
        List<MyModel> myModels = new List<MyModel>
        {
            new MyModel
            {
                ID = 1,
                Name = "Test1",
                Created = DateTime.Now,
                Creator = "Admin"
            },
            new MyModel
            {
                ID = 2,
                Name = "Test2",
                Created = DateTime.Now,
                Creator = "Admin"
            }
        };
        OkNegotiatedContentResult<List<MyModel>> result = new OkNegotiatedContentResult<List<MyModel>>(myModels, new ModelController());
        (await this.target.GetAsync() as OkNegotiatedContentResult<List<MyModel>>).Returns(result);

        OkNegotiatedContentResult<List<MyModel>> actual = (await this.target.GetAsync() as OkNegotiatedContentResult<List<MyModel>>);

        Assert.That(actual.Content.Count, Is.GreaterThanOrEqualTo(1)); // <== NullReferenceException because actual is null
    }
}

我得到一个NullReferenceException,因为“实际”为空。但是我不明白为什么。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我会像这样重新编写您的测试

[TestFixture]
public void GetAsync_GetAll_ReturnOkHttpResultWithListOfMyModels()
{
    List<MyModel> expectedModel = new List<MyModel>
    {
        new MyModel
        {
            ID = 1,
            Name = "Test1",
            Created = DateTime.Now,
            Creator = "Admin"
        },
        new MyModel
        {
            ID = 2,
            Name = "Test2",
            Created = DateTime.Now,
            Creator = "Admin"
        }
    };

    var sut = new ModelController();

    var result = sut.GetAsync();

    //check you can cast the result first
    Assert.That(result.Result, Is.AssignableTo<OkNegotiatedContentResult<IEnumerable<MyModel>>());

    var typedResult = (OkNegotiatedContentResult<IList<MyModel>>)result.Result;

    //Assert the actual data.
}

实例化您的ModelController。这是您正在测试的系统。您应该使用NSubstitute,Moq,FakeItEasy ...来模拟/伪造被测系统的依赖项。此时,您还没有任何东西。您提到了Dapper,因此一旦实现它就想模拟该依赖关系。

您也无需将测试方法标记为异步。

使用硬转换而不是“ as”将导致异常,如果它不能转换将导致测试失败。另外,您已经断言此强制转换应在上面的行中起作用。

这只是伪代码,不能保证运行。