Invalid return type when testing Async methods

5 posts, 0 answers
  1. Vikas
    Vikas avatar
    36 posts
    Member since:
    Dec 2015

    Posted 04 Jan Link to this post

    I have 2 classes Parent and a Child class, child class inherits from parent.

    Class under test has an async method that returns Task<parent>.

    I am arranging the Test method in my unit test, Mock.Arrange(() => viewmodel.Test()).Returns(Task.FromResult(new child()));

    I am getting this error, Why is it having a problem in casting a child to its parenttype

    ErrorCS1503Argument 1: cannot convert from 'System.Threading.Tasks.Task<ViewModels.child>' to 'System.Threading.Tasks.Task<ViewModels.parent>'ViewModels.Tests

    public class viewmodel{

    public async Task<parent> Test()
            {
                await Task.Delay(100);
                return null;              
            }
        }

        public class parent
        {

        }

        public class child : parent
        {

        }

  2. Vikas
    Vikas avatar
    36 posts
    Member since:
    Dec 2015

    Posted 04 Jan in reply to Vikas Link to this post

    If i change the arrange to this then it does not give compile time error:

    Mock.Arrange(() => viewmodel.Test()).Returns(Task.FromResult<parent>(new child()));

    But then i get invalid cast exception in the the code under test.

    this line of code in the class under test throws can not cast from Threading.Task.Task<parent> to Threading.Task.Task<child>

    child a  = await viewModel.Test() as child;

     

     

  3. DevCraft R3 2016 release webinar banner
  4. Vikas
    Vikas avatar
    36 posts
    Member since:
    Dec 2015

    Posted 04 Jan in reply to Vikas Link to this post

    It is working if i remove any expectations from the arrange like occurs(1). Does just mock supports expectations for async methods?
  5. Stefan
    Admin
    Stefan avatar
    198 posts

    Posted 05 Jan Link to this post

    Hi Vikas,

    Task<child> is not convertible to Task<parent>, because in .NET only interfaces and delegates, but not classes, may have convariant generic parameters. Explicitly specifying the type parameter of FromResult<T> is the correct way.

    This compiles:
    Task<parent> task = Task.FromResult<parent>(new child());
    This does not:
    Task<parent> task = Task.FromResult(new child());

    I tried the following code and I didn't get a type cast exception:
    public class parent
    {
    }
     
    public class child : parent
    {
    }
     
    public interface ITest
    {
        Task<parent> Test();
    }
     
    [TestMethod]
    public async Task Test()
    {
        var mock = Mock.Create<ITest>();
        Mock.Arrange(() => mock.Test())
            .Returns(Task.FromResult<parent>(new child()))
            .OccursOnce();
     
        child o = await mock.Test() as child;
    }
    A more complete example would help examine the issue.

    Regards,
    Stefan
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  6. Vikas
    Vikas avatar
    36 posts
    Member since:
    Dec 2015

    Posted 21 Jan in reply to Stefan Link to this post

    This works, Thanks
Back to Top
DevCraft R3 2016 release webinar banner