Модульное тестирование метода post с динамическим аргументом - PullRequest
0 голосов
/ 07 ноября 2018

В моем веб-контроллере API есть метод post, который принимает динамический аргумент

 public IEnumerable<Product> Post([FromBody]dynamic value)
    {
        int productId;
        try
        {
            productId = Convert.ToInt32(value.productId.Value);
        }
        catch
        {

            return null;
        }
        return _data.Products.Where(y => y.Id == productId).ToList();        
    }

Я пытаюсь провести модульное тестирование с использованием фрейма Moq, и это то, что у меня есть

 public void PostRequestWithSingleProductTest()

    {
        var reqBody = new {productId = 1};

        var reqObject = new Mock<HttpRequestMessage>();
        reqObject.Setup(rq => rq.ToString()).Returns(JsonConvert.SerializeObject(reqBody));

        var response = _productController.Post(reqObject.Object);


        Assert.IsNotNull(response);
    }

Ответ всегда равен нулю, и когда я отлаживаю тест, я вижу, что значение передается как {{productId: 1}}, но компилятор по какой-то причине не может прочитать это, и он выдает Microsoft.CSharp.Runtime.Binder Exception .

Я пометил тестовую сборку как друга, используя сборку: InternalsVisibleTo () .

Пожалуйста, поделитесь своими мыслями.

Спасибо.

1 Ответ

0 голосов
/ 08 ноября 2018

Проблема в том, что в тестируемом методе предполагается, что productId обнуляем, следовательно, .Value. Исключение происходит, когда тест передает фактическое целое число, а не обнуляемое целое.

public void PostRequestWithSingleProductTest() {
    //Arrange
    int? productId = 1;
    var value = new { productId };

    //assuming _productController already created and injected with dependency

    //Act
    var response = _productController.Post(value);

    //Assert
    Assert.IsNotNull(response);
}

В идеале вы должны использовать строго типизированную модель

public class PostProductModel {
    [Required]
    public int productId { get; set; }
}

Это позволило бы каркасу правильно связать модель

public IHttpActionResult Post([FromBody]PostProductModel value) {
    if(ModelState.IsValid) {
        var result = _data.Products.Where(y => y.Id == value.productId).ToList();        
        return Ok(result);
    }
    return BadRequest(ModelState);
 }

и значительно упростит возможность юнит-тестирования целевого метода.

public void PostRequestWithSingleProductTest() {
    //Arrange
    var value = new PostProductModel { productId = 1 };

    //assuming _productController already created and injected with dependency

    //Act
    var response = _productController.Post(value) as OkObjectResult;

    //Assert
    Assert.IsNotNull(response);
}
...