Модульное тестирование с подстановочными данными для асинхронных веб-интерфейсов - PullRequest
0 голосов
/ 14 декабря 2018

Я работаю над модульным тестом с 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 голосов
/ 14 декабря 2018

Я бы переписал ваш тест примерно так:

[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, так что вы захотите смоделировать эту зависимость, как только вы ее реализуете.

Вам не нужно также помечать метод теста как асинхронный.

Использовать жесткое приведение вместо«как» приведет к исключению, если он не может привести его, что провалит тест.Кроме того, вы уже заявили, что это приведение должно работать в приведенной выше строке.

Кроме того, это просто псевдокод, который не гарантированно выполняется.

...