4

I would like testing private method. When I setup FirstOrDefault method Moq thrown Exception. In my algorithm, I want check that, does my method properly create new objects. See my code below.

//Arrange
var data = new List<TypeValue>();

var typeValueMockSet = new Mock<DbSet<TypeValue>>();

typeValueMockSet
    .As<IList<TypeValue>>()
    .Setup(m => m.GetEnumerator())
    .Returns(data.GetEnumerator());

//throw the Error => Expression references a method that does not belong to the mocked object:
// m => m.FirstOrDefault<TypeValue>(It.IsAny<Expression`1>())
typeValueMockSet                                                                
    .Setup(m => m.FirstOrDefault(It.IsAny<Expression<Func<TypeValue, bool>>>()))
    .Returns(data.FirstOrDefault());

typeValueMockSet
    .Setup(m => m.Add(It.IsAny<TypeValue>()))
    .Returns((TypeValue vt) => vt)
    .Callback((TypeValue vt) => data.Add(vt));

var mockContext = new Mock<EngineeringWorkEntities>();
mockContext.Setup(m => m.TypeValues).Returns(typeValueMockSet.Object);

int counter = 0;
mockContext
    .Setup(m => m.SaveChanges())
    .Returns(0)
    .Callback(() => data
        .ForEach(
        (item) => 
        { 
            item.Id = counter;
            counter++;
        }));

//Act
IMakro makroDateGenerate = new MakroDataGenerate(mockContext.Object);

var pObj = new PrivateObject(makroDateGenerate);

int r1 = (int)pObj.Invoke("GetTypeValueId", "0,2% k/k");        //2 
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
matiii
  • 316
  • 4
  • 17
  • [I suggest not to test private members](http://stackoverflow.com/questions/21891918/whats-the-point-to-have-public-method-in-class-but-not-in-interface/21892183#21892183) also [here](http://stackoverflow.com/questions/9837050/questions-on-unit-testing-of-private-methods/9837139#9837139) – Sergey Berezovskiy Mar 15 '14 at 20:41
  • I'd like not generalize to much. Every case is different, so it's important a goal, why are you testing your code. If you eliminate a bugs, I think the goal was accomplished. – matiii Mar 16 '14 at 16:20

2 Answers2

2

You cannot mock FirstOrDefault because it is an extension method. It doesn't belongs to List<T> or anything else.

  • Yes, I agree, I hit on this, when I had a rest from computer – matiii Mar 16 '14 at 16:09
  • If you mock `GetEnumerator`, `FirstOrDefault` will work as that extension method calls `GetEnumerator()` through the use of `foreach` if it uses a predicate. If not, you need to mock `Count` and index 0. What I did was to create an Enumerator stub that takes an IEnumerable as constructor argument for convenience. – 4thex Nov 06 '18 at 14:48
0

You cannot test private methods other than by using Reflection in the unit tests. This is very cumbersome. You should test the public interface anyway.

Either make the method public or internal. If you make it internal, you can allow the unit test project to see it by the use of the InternalsVisibleToAttribute.

[assembly:InternalsVisibleTo("MyUnitTestProject")]
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188