Unit testing a post method with a dynamic argument
up vote
1
down vote
favorite
I have a post method in my web api controller that takes a dynamic argument
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();
}
I am trying to unit test this using the Moq frame work and this is what I have
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);
}
The response is always null, and when I debug the test I can see that the value is passed is as {{productId:1}} but the compiler is not able to read this for some reason and it's throwing a Microsoft.CSharp.Runtime.Binder Exception .
I have marked the test assembly as a friend using assembly: InternalsVisibleTo().
Please share your thoughts.
Thanks.
c# unit-testing asp.net-web-api asp.net-web-api2
add a comment |
up vote
1
down vote
favorite
I have a post method in my web api controller that takes a dynamic argument
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();
}
I am trying to unit test this using the Moq frame work and this is what I have
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);
}
The response is always null, and when I debug the test I can see that the value is passed is as {{productId:1}} but the compiler is not able to read this for some reason and it's throwing a Microsoft.CSharp.Runtime.Binder Exception .
I have marked the test assembly as a friend using assembly: InternalsVisibleTo().
Please share your thoughts.
Thanks.
c# unit-testing asp.net-web-api asp.net-web-api2
I would also just like to point out that the Post method works as expected. I am just not sure how to unit test in this example.
– febin
Nov 7 at 22:45
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have a post method in my web api controller that takes a dynamic argument
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();
}
I am trying to unit test this using the Moq frame work and this is what I have
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);
}
The response is always null, and when I debug the test I can see that the value is passed is as {{productId:1}} but the compiler is not able to read this for some reason and it's throwing a Microsoft.CSharp.Runtime.Binder Exception .
I have marked the test assembly as a friend using assembly: InternalsVisibleTo().
Please share your thoughts.
Thanks.
c# unit-testing asp.net-web-api asp.net-web-api2
I have a post method in my web api controller that takes a dynamic argument
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();
}
I am trying to unit test this using the Moq frame work and this is what I have
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);
}
The response is always null, and when I debug the test I can see that the value is passed is as {{productId:1}} but the compiler is not able to read this for some reason and it's throwing a Microsoft.CSharp.Runtime.Binder Exception .
I have marked the test assembly as a friend using assembly: InternalsVisibleTo().
Please share your thoughts.
Thanks.
c# unit-testing asp.net-web-api asp.net-web-api2
c# unit-testing asp.net-web-api asp.net-web-api2
edited Nov 8 at 10:00
Nkosi
104k15111178
104k15111178
asked Nov 7 at 16:57
febin
82
82
I would also just like to point out that the Post method works as expected. I am just not sure how to unit test in this example.
– febin
Nov 7 at 22:45
add a comment |
I would also just like to point out that the Post method works as expected. I am just not sure how to unit test in this example.
– febin
Nov 7 at 22:45
I would also just like to point out that the Post method works as expected. I am just not sure how to unit test in this example.
– febin
Nov 7 at 22:45
I would also just like to point out that the Post method works as expected. I am just not sure how to unit test in this example.
– febin
Nov 7 at 22:45
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
accepted
The problem is that the method under test assumes that the productId
is nullable, hence the .Value
. The exception happens as the test passes an actual integer and not a nullable integer.
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);
}
Ideally you should be using a strongly typed model
public class PostProductModel {
[Required]
public int productId { get; set; }
}
That would allow for the framework to do proper model binding
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);
}
and greatly simplify the ability to unit test the target method.
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);
}
Thanks a lot for your comment, I did not realise the role of nullable int here. I am still learning my way through web api / mvc etc.. using asp.net. Thanks for providing the right pattern for addressing this problem.
– febin
Nov 8 at 11:12
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
The problem is that the method under test assumes that the productId
is nullable, hence the .Value
. The exception happens as the test passes an actual integer and not a nullable integer.
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);
}
Ideally you should be using a strongly typed model
public class PostProductModel {
[Required]
public int productId { get; set; }
}
That would allow for the framework to do proper model binding
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);
}
and greatly simplify the ability to unit test the target method.
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);
}
Thanks a lot for your comment, I did not realise the role of nullable int here. I am still learning my way through web api / mvc etc.. using asp.net. Thanks for providing the right pattern for addressing this problem.
– febin
Nov 8 at 11:12
add a comment |
up vote
0
down vote
accepted
The problem is that the method under test assumes that the productId
is nullable, hence the .Value
. The exception happens as the test passes an actual integer and not a nullable integer.
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);
}
Ideally you should be using a strongly typed model
public class PostProductModel {
[Required]
public int productId { get; set; }
}
That would allow for the framework to do proper model binding
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);
}
and greatly simplify the ability to unit test the target method.
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);
}
Thanks a lot for your comment, I did not realise the role of nullable int here. I am still learning my way through web api / mvc etc.. using asp.net. Thanks for providing the right pattern for addressing this problem.
– febin
Nov 8 at 11:12
add a comment |
up vote
0
down vote
accepted
up vote
0
down vote
accepted
The problem is that the method under test assumes that the productId
is nullable, hence the .Value
. The exception happens as the test passes an actual integer and not a nullable integer.
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);
}
Ideally you should be using a strongly typed model
public class PostProductModel {
[Required]
public int productId { get; set; }
}
That would allow for the framework to do proper model binding
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);
}
and greatly simplify the ability to unit test the target method.
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);
}
The problem is that the method under test assumes that the productId
is nullable, hence the .Value
. The exception happens as the test passes an actual integer and not a nullable integer.
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);
}
Ideally you should be using a strongly typed model
public class PostProductModel {
[Required]
public int productId { get; set; }
}
That would allow for the framework to do proper model binding
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);
}
and greatly simplify the ability to unit test the target method.
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);
}
edited Nov 8 at 11:12
answered Nov 8 at 9:57
Nkosi
104k15111178
104k15111178
Thanks a lot for your comment, I did not realise the role of nullable int here. I am still learning my way through web api / mvc etc.. using asp.net. Thanks for providing the right pattern for addressing this problem.
– febin
Nov 8 at 11:12
add a comment |
Thanks a lot for your comment, I did not realise the role of nullable int here. I am still learning my way through web api / mvc etc.. using asp.net. Thanks for providing the right pattern for addressing this problem.
– febin
Nov 8 at 11:12
Thanks a lot for your comment, I did not realise the role of nullable int here. I am still learning my way through web api / mvc etc.. using asp.net. Thanks for providing the right pattern for addressing this problem.
– febin
Nov 8 at 11:12
Thanks a lot for your comment, I did not realise the role of nullable int here. I am still learning my way through web api / mvc etc.. using asp.net. Thanks for providing the right pattern for addressing this problem.
– febin
Nov 8 at 11:12
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53194231%2funit-testing-a-post-method-with-a-dynamic-argument%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I would also just like to point out that the Post method works as expected. I am just not sure how to unit test in this example.
– febin
Nov 7 at 22:45