This is a migrated thread and some comments may be shown as answers.

How to mock Asynchronous Methods?

12 Answers 989 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Md.Hasanuzzaman
Top achievements
Rank 1
Md.Hasanuzzaman asked on 03 Jan 2014, 05:53 PM
Dear sir,
Now I am in a new problem. I am unable to Mock Asynchronous Methods.

Here is my code which I try for :

 My Class :

 public class BaseRepository<T> : IRepositoryBase<T> where T : class, IEntity, new()
    {
        protected readonly DbContext InnerDbContext;
        protected DbSet<T> InnerDbSet;

        public BaseRepository(DbContext innerDbContext)
        {
            InnerDbContext = innerDbContext;
            InnerDbSet = InnerDbContext.Set<T>();
        }

        public virtual void Add(T entity)
        {
            InnerDbSet.Add(entity);
        }

        public virtual async Task UpdateAsync(T entity)
        {
            var newEntry = InnerDbContext.Entry(entity);
            if (newEntry.State != EntityState.Detached)
            {
                var oldEntity = await FindAsync(entity.Id);
                if (oldEntity == null)
                    throw new EntityNotFound();
                var attachEntity = InnerDbContext.Entry(oldEntity);
                attachEntity.CurrentValues.SetValues(newEntry);
            }
            else
            {
                newEntry.State = EntityState.Modified;
            }
        }

        public virtual async Task RemoveAsync(T entity)
        {
            entity.IsDelete = true;
            await UpdateAsync(entity);
        }

        public virtual IQueryable<T> All()
        {
            return InnerDbSet.Where(x => !x.IsDelete);
        }

        public virtual Task<T> FindAsync(long id)
        {
            return InnerDbSet.FirstOrDefaultAsync(x => x.Id == id && !x.IsDelete);
        }

        public virtual IQueryable<T> Search(Expression<Func<T, bool>> expression)
        {
            return InnerDbSet.Where(x => x.IsDelete)
                .Where(expression);
        }
    }

My Test :

       readonly TimeSketchContext _mockDataContext = Mock.Create<TimeSketchContext>();
        private readonly BaseRepository<EmployeeSkill> _repository;
        public BaseRepositoryTest()
        {
            _repository = new BaseRepository<EmployeeSkill>(_mockDataContext);
        }

        [Fact]
        public async void Find_Should_Call_Once()
        {
            await _repository.FindAsync(Arg.AnyInt);
            Mock.Assert(() => _mockDataContext.Set<EmployeeSkill>().FirstOrDefaultAsync(x => x.Id == Arg.AnyInt && !x.IsDelete), Occurs.Once());
            // Mock.Assert(() => _mockDataContext.Set<EmployeeSkill>().LastOrDefault(x => x.Id == Arg.AnyInt && !x.IsDelete), Occurs.Once());  test is pass !!!

        }
       above test is also  pass if  change this FirstOrDefaultAsync to LastOrDefault

        [Fact]
        public async void Update_Should_Call_Once()
        {
            var employeeSkill = GetEmployeeSkill();
            employeeSkill.SkillName = "Skill Update";
            await _repository.UpdateAsync(employeeSkill);
            Mock.Assert(() => _repository.FindAsync(Arg.AnyInt), Occurs.Once());
        }
   
       Same Problem.
        
       [Fact]
        public async void Remove_Should_Call_Update()
        {
            await _repository.RemoveAsync(Arg.IsAny<EmployeeSkill>());
            Mock.Assert(() => _repository.UpdateAsync(Arg.IsAny<EmployeeSkill>()), Occurs.Once());
        }

Thank`s in Advance.

12 Answers, 1 is accepted

Sort by
0
Kaloyan
Telerik team
answered on 06 Jan 2014, 10:15 AM
Hello Md.Hasanuzzaman,

To investigate the matter, we will require a sample project, reproducing the issue. You should be able to attach the project with the next reply in this thread. Please, let us know if this is doable for you.

Thank you for the understanding and the cooperation in advance.

Regards,
Kaloyan
Telerik
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
Md.Hasanuzzaman
Top achievements
Rank 1
answered on 08 Jan 2014, 05:23 PM
Here is my Simple Project 

JustMockTest.zip

Please Check It
0
Kaloyan
Telerik team
answered on 10 Jan 2014, 02:27 PM
Hello Md.Hasanuzzaman,

Thank you for the project. Unfortunately, investigating it I came across an issue in JustMock that prevents mocking in multi-threaded scenarios. In other words, with the current version of JustMock you cannot arrange expectations for async functions.

We will need some time in order to find the best solution for this and implement it into our product.

I apologize for the inconveniences caused by this.

I will be happy to contact you once again when the issue is resolved.

Further, here is an applicable scenario that tests the Add method of your BaseRepository class:
[Fact]
public void Add_Should_Call_Once()
{
    // Arrange
    Mock.Arrange(() => _mockDataContext.Set<EmployeeSkill>().Add(Arg.IsAny<EmployeeSkill>())).Occurs(1);
     
    // Act
    _repository.Add(GetEmployeeSkill());
     
    // Assert
    Mock.Assert(_mockDataContext);
}

Regards,
Kaloyan
Telerik
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
Md.Hasanuzzaman
Top achievements
Rank 1
answered on 10 Jan 2014, 05:32 PM
i hope we will get it soon. Thanks.
0
Ludmila
Top achievements
Rank 1
answered on 12 Feb 2015, 05:07 PM
I have the same issue with 2014.3.1021.2
Are there any plans to fix it?
0
Brandon Hunt
Top achievements
Rank 2
answered on 16 Feb 2015, 02:19 PM
[quote]
I have the same issue with 2014.3.1021.2
Are there any plans to fix it?
[/quote]

Same here.  

I'm starting to run into the same issue now in 2014.3.1021.2 as well.  We've got a number of async calls that fire off for reports and such.  Of possible interest, if I do a test to see if the "async" method gets called, the Mock.Assert passes if I just run that test solo, but if I do a Run All (or any run that involves multiple tests), the Mock.Assert for the async call fails (telling me it wasn't called at all - I've got an OccursOnce validation on that call and that's what fails).
0
Ludmila
Top achievements
Rank 1
answered on 16 Feb 2015, 04:40 PM
using NUnit.Framework;
using System.IO;
using System.Threading.Tasks;
using Telerik.JustMock;

namespace JustMockTest
{
    public class MyClass
    {
        public async Task DoSomething()
        {
            var data = new byte[]{1, 2, 3};
            using (var inputFileStream = File.OpenWrite("in.txt"))
                await inputFileStream.WriteAsync(data, 0, data.Length).ConfigureAwait(false);

            using (var outputFileStream = File.OpenRead("in.txt"))
                await outputFileStream.ReadAsync(data, 0, data.Length).ConfigureAwait(false);
        }

        [Test]
        public void TestWriteAsync()
        {
            Mock.Arrange(() => File.OpenWrite(Arg.AnyString)).Throws(new IOException());
            Assert.That(async () => await DoSomething(), Throws.Exception.TypeOf<IOException>());
        }

        [Test]
        public void TestReadAsync()
        {
            Mock.Arrange(() => File.OpenRead(Arg.AnyString)).Throws(new IOException());
            Assert.That(async () => await DoSomething(), Throws.Exception.TypeOf<IOException>());
        }
    }
}

In above example, TestWriteAsync works correct and passes. TestReadAsync always fails because IOException is not fired on read.
Here is the code
0
Stefan
Telerik team
answered on 17 Feb 2015, 09:16 AM
Hello Ludmila,

Static and future mocking across threads needs to be explicitly enabled for every applicable arrangement individually using the .OnAllThreads() clause:
Mock.Arrange(() => File.OpenRead(Arg.AnyString)).Throws(new IOException()).OnAllThreads();


Regards,
Stefan
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Ludmila
Top achievements
Rank 1
answered on 17 Feb 2015, 11:15 AM
Thank you, it works!
0
Stefan
Telerik team
answered on 17 Feb 2015, 11:28 AM
Hello Brandon,

To further help us understand your exact issue, I'd like to ask you for a repro project or a complete snippet of code demonstrating the issue.

Regards,
Stefan
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Brandon Hunt
Top achievements
Rank 2
answered on 17 Feb 2015, 02:30 PM
I'll see if I can get one pulled together - might take a day or two though.  I'm pretty sure you don't want / need a 50k LOC production app. :)
0
Brandon Hunt
Top achievements
Rank 2
answered on 17 Feb 2015, 06:06 PM
Stefan, I put this in as a support ticket as i had to use a pretty significant subset of our production codebase to repro the problem I'm running into.  It's ticket 907693.

Thanks!
Tags
General Discussions
Asked by
Md.Hasanuzzaman
Top achievements
Rank 1
Answers by
Kaloyan
Telerik team
Md.Hasanuzzaman
Top achievements
Rank 1
Ludmila
Top achievements
Rank 1
Brandon Hunt
Top achievements
Rank 2
Stefan
Telerik team
Share this question
or