1

It is understood that:

Expression<Func<string, bool>> first = x => x.Length == 4;
Expression<Func<string, bool>> second = x => x.Length == 4;

Console.WriteLine(first.Equals(second)); // Output is "False"

However, examining the strings of each expression does show equality:

Expression<Func<string, bool>> first = x => x.Length == 4;
Expression<Func<string, bool>> second = x => x.Length == 4;

Console.WriteLine(first.ToString().Equals(second.ToString())); // Output is "True"

This idea was a culmination of different posts...

http://www.codethinked.com/Comparing-Simple-Lambda-Expressions-With-Moq Moq'ing methods where Expression<Func<T, bool>> are passed in as parameters Verify method was called with certain linq expression (moq)

The intent:

I am writing an MVC application using the repository pattern such that

public class MyController : Controller
{
    public Repository.IRepository Repository { get; set; }

    public MyController()
    {
        this.Repository = new Repository.CommonRepository();
    }

    public MyController(Repository.IRepository repository)
    {
        this.Repository = repository;
    }

    [HttpPost]
    public ActionResult Create(Domain.Common.Object1 o1)
    {
        if (ModelState.IsValid)
        {
            // Additional validation
            o1.Name = o1.Name.Trim();

            if (this.Repository.Any<Domain.Common.Object1>(a => a.Name.ToLower() == plant.Name.ToLower()))
                this.ModelState.AddModelError("Name", "Duplicate found.");
        }

        if (ModelState.IsValid)
        {
            var entity = this.Repository.Add(o1);

            if (Request.IsAjaxRequest())
                return this.Json(new { Completed = true, Id = entity.Id });

            return RedirectToAction("Details", new { id = entity.Id });
        }

        if (Request.IsAjaxRequest())
            return PartialView("_Create", o1);

        return View("Create", o1);
    }
}

Repository is a completely separate project as is the domain. My repository code is setup so that I can use the one repository to query any object based upon the generic:

public IQueryable<T> GetAll<T>() where T : AbstractEntity
{
    return this.DbContext.Set<T>();
}

Note: AbstractEntity is a domain abstract class all of my POCO objects inherit from.

Everything is fine when using Moq to unit test the controller :

[TestMethod]
public void Create_Post_DuplicateNameAddsError()
{
    // Arrange
    var repository = new Mock<Repository.IRepository>();

    repository.Setup(a => a.Any<Domain.Common.Object1>(It.IsAny<System.Linq.Expressions.Expression<Func<Domain.Common.Object1, bool>>>()))
              .Returns(true);

    var controller = ControllerFactory<MyController>.GetController();
    controller.Repository = repository.Object;

    var model = new Domain.Common.Object1()
    {
        Id = Guid.NewGuid()
        ,
        Name = "Name"
    };



    // Act
    var result = controller.Create(model) as ViewResult;



    // Assert
    Assert.IsFalse(controller.ModelState.IsValid);

    Assert.IsNotNull(result);
    Assert.AreEqual("Create", result.ViewName, false);

    Assert.AreEqual(model, result.Model);
}

Note: ControllerFactory is a way to generate a controller with certain properties filled, such as Request, Response, User, Request.Headers ect...

Where this fails is if I have to use IRepository.Any(predicate) more than once, or any method that uses expressions that is called more than once. I need it to say true for one and false for another. If the expression strings were a match, this would be a non-issue, but as everything is in different projects the expression strings come out as:

a => (a.Name.ToLower() == value(foo.Web.Tests.Controllers.Object1ControllerTests+<>c__DisplayClass3).ob1.Name.ToLower())
a => (a.Name.ToLower() == value(foo.Controllers.MyController+<>c__DisplayClass1).ob1.Name.ToLower())

The difference lies in the value function. I have tried matching from Regular Expressions, which works, but is ugly as you have to escape every .<>(), which in turn makes it very difficult to maintain.

I tried using Matt Meber's Expression Equality Comparer, but they are not equal due to that value function (my belief).

Suggestions?

Community
  • 1
  • 1
user1097974
  • 53
  • 2
  • 6

0 Answers0