2 Replies - 134 Views - Last Post: 06 June 2020 - 08:50 PM Rate Topic: -----

#1 rgfirefly24   User is offline

  • D.I.C Lover
  • member icon


Reputation: 473
  • View blog
  • Posts: 2,221
  • Joined: 07-April 08

Comparing to Expressions for equality

Posted 06 June 2020 - 01:34 PM

I am attempting to unit test some functions that interact with Entity framework. In our IRepository we have a function FirstOrDefaultAsync which take in two Expressions. Using MOQ I've created a mock IRepository, but can not seem to get the setup to work properly for said function.

Function I'm trying to Setup:
        public virtual async Task<TEntity> FirstOrDefaultAsync(bool validateOwnership, Expression<Func<TEntity, bool>> filter,
            params Expression<Func<TEntity, object>>[] includes)
        {
            IQueryable<TEntity> query = Query();

            if (includes != null && includes.Length > 0)
                foreach (Expression<Func<TEntity, object>> include in includes)
                    query = query.Include(include);

            TEntity entity = await query.FirstOrDefaultAsync(filter);

            if (validateOwnership)
                ValidateOwnership(entity);

            return entity;
        }



Here is my current attempt at the setup:
            mockIRepositoryMenuRole.Setup(m => m.FirstOrDefaultAsync(It.IsAny<bool>(),
                                        It.Is<Expression<Func<MenuRole, bool>>>(i => i.ToString() == successTestExpression.ToString()), It.IsAny<Expression<Func<MenuRole,object>>>()))
                .ReturnsAsync((MenuRole)null);
            mockIRepositoryMenuRole.Setup(m => m.FirstOrDefaultAsync(It.IsAny<bool>(),
                                        It.Is<Expression<Func<MenuRole, bool>>>(i => i.ToString() == existingTestExpression.ToString()), It.IsAny<Expression<Func<MenuRole, object>>>()))
                 .ReturnsAsync(MenuRoleFixture.ExistingMenuRole);



I've tried just doing i => i == successTestExpression, i.Equals(successTestExpression) and using Func<Expression, Expression, bool> eq = ExpressionEqualityComparer.Instance.Equals; and each attempt resulted in always returning null. I checked that it was just not hitting the first setup by having to return a Fixture and it still comes back null.

here are the test expressions:
Expression<Func<MenuRole, bool>> successTestExpression = i => i.MenuItemId == CreateMenuRoleMapFixture.SuccessCreateMenuRoleMap.MenuId 
                                                                        && i.RoleId == CreateMenuRoleMapFixture.SuccessCreateMenuRoleMap.RoleId;
            Expression<Func<MenuRole, bool>> existingTestExpression = i => i.MenuItemId == CreateMenuRoleMapFixture.SuccessExistingCreateMenuRoleMap.MenuId 
                                                                        && i.RoleId == CreateMenuRoleMapFixture.SuccessExistingCreateMenuRoleMap.RoleId;



here is the call that is supposed to be using those:
var roleMenu = await _unitOfWork.MenuRoles.FirstOrDefaultAsync(false,i => i.MenuItemId == command.MenuId && i.RoleId == command.RoleId,null);



Any ideas how I can compare the incoming Expression against a known test one and return a specific response based on that?

Is This A Good Question/Topic? 0
  • +

Replies To: Comparing to Expressions for equality

#2 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7391
  • View blog
  • Posts: 24,952
  • Joined: 05-May 12

Re: Comparing to Expressions for equality

Posted 06 June 2020 - 06:33 PM

Can you do the brute force of converting each expression to a string (e.g. .ToString()) and see if the two are equal. I know, it's brute force, but it's also just a unit test.

Or are you looking for equivalency between two expression trees? In which case, you'll likely need to simplify both trees, and then walk the simplified trees to see if they are equivalent. I've forgotten way too much of my compiler designer and graph theory to be able to guide you in the find details of how to do this, though.
Was This Post Helpful? 0
  • +
  • -

#3 rgfirefly24   User is offline

  • D.I.C Lover
  • member icon


Reputation: 473
  • View blog
  • Posts: 2,221
  • Joined: 07-April 08

Re: Comparing to Expressions for equality

Posted 06 June 2020 - 08:50 PM

I tried using ToString and it didn't seem to help.

I've updated it to also use an array for the 2nd parameter since it's a params. I missed that part previously:

            Expression<Func<MenuRole, bool>> successTestExpression = i => i.MenuItemId == CreateMenuRoleMapFixture.SuccessCreateMenuRoleMap.MenuId 
                                                                        && i.RoleId == CreateMenuRoleMapFixture.SuccessCreateMenuRoleMap.RoleId;
            Expression<Func<MenuRole, bool>> existingTestExpression = i => i.MenuItemId == CreateMenuRoleMapFixture.SuccessExistingCreateMenuRoleMap.MenuId 
                                                                        && i.RoleId == CreateMenuRoleMapFixture.SuccessExistingCreateMenuRoleMap.RoleId;

            mockIRepositoryMenuRole.Setup(m => m.FirstOrDefaultAsync(It.IsAny<bool>(),
                                        It.Is<Expression<Func<MenuRole, bool>>>(i => i.ToString() == successTestExpression.ToString()), It.IsAny<Expression<Func<MenuRole, object>>[]>()))
                .ReturnsAsync((MenuRole)null);
            mockIRepositoryMenuRole.Setup(m => m.FirstOrDefaultAsync(It.IsAny<bool>(),
                                        It.Is<Expression<Func<MenuRole, bool>>>(i => i.ToString() == existingTestExpression.ToString()), It.IsAny<Expression<Func<MenuRole, object>>[]>()))
                 .ReturnsAsync(MenuRoleFixture.ExistingMenuRole);


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1