Reputation: 23
The return type of result and expected are different unable to fake an async method my code on x unit testing
using Amazon.Controllers;
using Amazon.Models;
using Amazon.Repository;
using FakeItEasy;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AmazonAPITest.Amazon_Controller_Merchant
{
public class Merchant_Controller_Test
{
private readonly IMerchantRepository _merchantRepository;
public Merchant_Controller_Test()
{
_merchantRepository = A.Fake<IMerchantRepository>();
}
[Fact]
public void MerchantController_GetMerchants_ListMerchantAsync()
{
//Arrange
var MerchantList = A.Fake<Task<List<Merchant>>>();
A.CallTo(() => _merchantRepository.GetMerchant()).Returns(MerchantList);
var MerchantController = new MerchantController(_merchantRepository);
var expected = A.Fake<Task<ActionResult<List<Merchant>>>>();
//Act
var result= MerchantController.GetMerchants();
//Assert
result.Should().NotBeNull();
result.Should().BeOfType<Task<ActionResult<List<Merchant>>>>();
}
}
}
controller action method code
[HttpGet]
public async Task<ActionResult<List<Merchant>>> GetMerchants()
{
return await _repository.GetMerchant();
}
repository code
public async Task<List<Merchant>> GetMerchant()
{
try
{
return await _context.Merchants.ToListAsync();
}
catch
{
throw new NotImplementedException();
}
}
exception on debugging the test
Xunit.Sdk.XunitException: 'Expected type to be System.Threading.Tasks.Task1[[Microsoft.AspNetCore.Mvc.ActionResult
1[[System.Collections.Generic.List1[[Amazon.Models.Merchant, AmazonAPI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]]**, but found **System.Runtime.CompilerServices.AsyncTaskMethodBuilder
1+AsyncStateMachineBox1[[Microsoft.AspNetCore.Mvc.ActionResult
1[[System.Collections.Generic.List`1[[Amazon.Models.Merchant, AmazonAPI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Runtime.CompilerServices.IAsyncStateMachine, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].
can someone figure any way to fake async method with fake it easy
Upvotes: 1
Views: 875
Reputation: 241714
The problem isn't in faking the async method. It's how you've defined the return value:
var MerchantList = A.Fake<Task<List<Merchant>>>();
A fake Task<List<Merchant>>
is not a Task<ActionResult<List<Merchant>>>
.
When I replace your definition with
var MerchantList = new List<Merchant>();
(and supply a definition for MerchantController
)
the test passes. It's also easier to understand: an empty list is more familiar to the reader than a faked list. I'd recommend using concrete objects for your return values whenever possible.
(Also note that expected
is unused in your example.)
My updated code, based on your expanded example:
// using Amazon.Controllers;
// using Amazon.Models;
// using Amazon.Repository;
using FakeItEasy;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AmazonAPITest.Amazon_Controller_Merchant
{
public interface IMerchantRepository
{
Task<List<Merchant>> GetMerchant();
}
public class Merchant
{
}
public class MerchantController
{
private readonly IMerchantRepository _repository;
public MerchantController(IMerchantRepository repository) => _repository = repository;
public async Task<ActionResult<List<Merchant>>> GetMerchants() => await _repository.GetMerchant();
}
public class Merchant_Controller_Test
{
private readonly IMerchantRepository _merchantRepository;
public Merchant_Controller_Test()
{
_merchantRepository = A.Fake<IMerchantRepository>();
}
[Fact]
public void MerchantController_GetMerchants_ListMerchantAsync()
{
//Arrange
// THIS IS THE ONLY CHANGE I MADE TO THE TEST
// var MerchantList = A.Fake<Task<List<Merchant>>>();
var MerchantList = new List<Merchant>();
A.CallTo(() => _merchantRepository.GetMerchant()).Returns(MerchantList);
var MerchantController = new MerchantController(_merchantRepository);
var expected = A.Fake<Task<ActionResult<List<Merchant>>>>();
//Act
var result = MerchantController.GetMerchants();
//Assert
result.Should().NotBeNull();
result.Should().BeOfType<Task<ActionResult<List<Merchant>>>>();
}
}
}
Aside from this change, I would also ask you to consider why you're checking the type of the return value. It's a sort of weak condition, while also being brittle. A stronger and probably less fragile test might use the returned value to see if it has expected properties, such as the right contents. But perhaps you've simplified for reproduction benefits.
Upvotes: 1