2

I have a repository that I fake and I need based on expression return different values

A.CallTo(() => repository.FirstOrDefaultAsync<Group>(x => x.Id == busMessage.Id && x.GroupType == ObjectType.Office)).Returns(dbOffice);
A.CallTo(() => repository.FirstOrDefaultAsync<Group>(x => x.Id == busMessage.Id && x.GroupType == ObjectType.Country)).Returns(dbCountry);

I have tried different ways but without luck any suggestions are appreciated

Burim Hajrizaj
  • 383
  • 4
  • 14
  • Possible duplicate of [How to test for a Match with FakeItEasy on a predicate call?](https://stackoverflow.com/questions/21437044/how-to-test-for-a-match-with-fakeiteasy-on-a-predicate-call) – Blair Conrad Mar 06 '19 at 12:11
  • 1
    As discussed [in gitter](https://gitter.im/FakeItEasy/FakeItEasy?at=5c7f8f761c597e5db69082ad), the difficulty comes down to the fact that `Expression`s don't implement value-type `Equals`, and some extra work will have to be done to establish that the expressions are the same. This was explored in [How to test for a Match with FakeItEasy on a predicate call?](https://stackoverflow.com/questions/21437044/how-to-test-for-a-match-with-fakeiteasy-on-a-predicate-call). – Blair Conrad Mar 06 '19 at 12:13

1 Answers1

2

Try defining your expression separately. It worked for me.

using System;
using NUnit.Framework;
using FakeItEasy;
using System.Linq.Expressions;

namespace ClassLibraryTests
{
    [TestFixture]
    public class IRepositoryTests
    {
        private IRepository CreateSut(Expression<Func<Group, bool>> expression, object result)
        {
            IRepository sut = A.Fake<IRepository>();
            A.CallTo(() => sut.FirstOrDefaultAsync<Group>(expression)).Returns(result);
            return sut;
        }

        [Test]
        public void FirstOrDefaultAsyncTests_Office()
        {
            // Arrange    
            BusMessage busMessage = new BusMessage();
            Expression<Func<Group, bool>> expression = x => x.Id == busMessage.Id && x.GroupType == ObjectType.Office;
            object dbOffice = new object();

            IRepository repository = this.CreateSut(expression, dbOffice);

            // Act
            object obj = repository.FirstOrDefaultAsync<Group>(expression);

            //Assert
            Assert.AreEqual(obj, dbOffice);
        }

        [Test]
        public void FirstOrDefaultAsyncTests_Country()
        {
            // Arrange    
            BusMessage busMessage = new BusMessage();           
            Expression<Func<Group, bool>> expression = x => x.Id == busMessage.Id && x.GroupType == ObjectType.Country;
            object dbCountry = new object();

            IRepository repository = this.CreateSut(expression, dbCountry);

            // Act
            object obj = repository.FirstOrDefaultAsync<Group>(expression);

            //Assert
            Assert.AreEqual(obj, dbCountry);
        }
    }

    public interface IRepository
    {
        object FirstOrDefaultAsync<T>(Expression<Func<T, bool>> expression);
    }

    public class Group
    {
        public ObjectType GroupType { get; set; }
        public int Id { get; set; }
    }

    public class BusMessage
    {
        public int Id { get; set; }
    }

    public enum ObjectType
    {
        Office,
        Country
    }
}
CSDev
  • 3,177
  • 6
  • 19
  • 37
  • 1
    Based on the [Gitter discussion](https://gitter.im/FakeItEasy/FakeItEasy?at=5c7f8f761c597e5db69082ad), the expressions are actually expression trees (`Expression>`). Anyway, the problem with the approach you suggest is that the system under test (the class that depends on `IRepository`) probably creates the expression itself, so there's no way to pass the expression to it. As you wrote it, the test doesn't actually test any application code; it just tests that FakeItEasy works as it should ;) – Thomas Levesque Mar 06 '19 at 12:43
  • Totally agree! But we do not have context. May be the dbOffice is obtained inside some method and affects its result. And expression can be passed into system under test via IRepository CreateSut(Func func, object result) method. – CSDev Mar 06 '19 at 12:54