Как смоделировать методы, вызываемые из функции Azure? - PullRequest
0 голосов
/ 26 февраля 2019

Проблема функций Azure заключается в том, что их функция Run должна быть статической.Эта функция Run вызывает функцию, которая выполняет поисковый запрос к базе данных.Я хотел бы издеваться над этой функцией

namespace Something.App{
    public class Something {        
        [FunctionName("Something")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
            ILogger log)
        {   
            //perform something
            dbCall(); // I wish to mock
            //perform something
            return new OkObjectResult(result); 
        }

Однако попытки насмехаться над этим не увенчались успехом.Сам тест выполнялся, но он не запускает макетную версию, он просто запускает оригинальную версию, которая использует подключение к Интернету.

namespace Something.Test{
    public class SomethingTest{
        private readonly ILogger logger = TestFactory.CreateLogger();

        private Mock<Something> CreateMockObject(){

            var mock = new Mock<Something>();

            mock.SetupSequence(f => f.dbCall()).Returns(something);
            return mock;
        }

        [Fact]

        public async void Http_Respond_On_Valid_Data()
        {
            CreateMockObject();
            Dictionary<string,StringValues> postParam= new Dictionary<string,StringValues>();
            postParam.Add("param", "value");

            var request = new DefaultHttpRequest(new DefaultHttpContext()){
                Query = new QueryCollection(postParam)
            };

            var response = (OkObjectResult)await Something.Run(request, logger);
            string stringResponse = (String) response.Value;
            Assert.Equal("XKCD", stringResponse);
        }

Я попытался разделить метод на нестатический класс (скажем,SomethingTool) и добиться чего-то подобного.

namespace Something.App{
    public class Something {        
        [FunctionName("Something")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
            ILogger log)
        {   
            SomethingTool object = new SomethingTool();
            //perform something
            object.dbCall(); // I wish to mock
            //perform something
            return new OkObjectResult(result); 
        }

Но это не совсем то, что нужно.Для этого проекта использование Moq является обязательным.

1 Ответ

0 голосов
/ 26 февраля 2019

Самый простой подход - это реорганизовать функцию для абстрагирования зависимостей, чтобы при необходимости их можно было заменить при тестировании

Например,

public static class Something {

    public static Func<ISomeDependency> Factory = () => return new SomeDependency();

    [FunctionName("Something")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
        ILogger log) { 

        //...

        ISomeDependency tool = Factory.Invoke();
        var result = await tool.dbCall();

        //...

        return new OkObjectResult(result); 
    }
}

, который теперь можно протестировать как

public class SomethingTest{
    private readonly ILogger logger = TestFactory.CreateLogger();

    [Fact]
    public async Task Http_Respond_On_Valid_Data() {
        //Arrange
        var expected = "XKCD";
        var mock = new Mock<ISomeDependency>();
        mock.Setup(_ => _.dbCall()).ReturnsAsync(expected);

        Something.Factory = () => return mock.Object; //<-- replace factory delegate

        var postParam = new Dictionary<string, StringValues>();
        postParam.Add("param", "value");

        var request = new DefaultHttpRequest(new DefaultHttpContext()){
            Query = new QueryCollection(postParam)
        };

        //Act
        var response = (OkObjectResult)await Something.Run(request, logger);
        string actual = (String) response.Value;

        //Assert
        Assert.Equal(expected, actual);
    }
}

Реальная реализация будет использовать функцию при вызове, но ее можно заменить заводским методом при модульном тестировании функции в изоляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...