1

SITUATION

I have the following code here

ITest.cs

public interface ITest { int Prop { get; } int Calc(); } 

Test.cs

public class Test : ITest { public int Prop { get; private set; } public int Calc() { return Prop * 2; } } 

And I want to test the Calc() method. If my understanding is correct You can NOT override the getter property of concrete classes without using the virtual keyword.

for example

var moq = new Mock<Test>(); // mocked Test class moq.Setup(x => x.Prop).Returns(2); // throws an error, // however with "virtual int Prop { get; }" it doesn't throw any exceptions 
var moq = new Mock<ITest>(); // mocked ITest interface moq.Setup(x => x.Prop).Returns(2); // works fine // but can not really test the Calc() method (it returns 0 // because the proxy doesn't have Test's implementation) 

QUESTION

so my question is: how can I test the functionality of Calc() without making virtual int Prop

btw... this doesn't work either

var moq = new Mock<ITest>(); moq.Setup(x => x.Prop).Returns(2); var obj = (Test)moq.Object; // can NOT convert ITestProxy to Test 
14
  • 3
    What are you trying to achieve? I f you want to test the Test class, then don't mock it. Commented Apr 29, 2020 at 9:05
  • 5
    @Hrant I can't get the point of your question. If you need to unit test the Calc method of the class Test, you do NOT need to mock anything. Test is a concrete class and you want to unit test one of its public methods, right ? So you simply need to instantiate the class call the method and write down some asserts. Commented Apr 29, 2020 at 9:05
  • 1
    @EnricoMassone why that? It's extremely simple: I can NOT instantiate the Test class and override it's PROP in order to Test my CALC() method. Commented Apr 29, 2020 at 9:10
  • 1
    @Hrant you need to provide a way for class user to set the value of Prop. That's the only point. You do not need to mock anything. You need to change the class public surface so that someone using it is able to set a value for Prop. This does not necessarily mean to change the visibility of the setter to public. Commented Apr 29, 2020 at 9:14
  • 2
    @Hrant I think you are misunderstand what moq does. Anything mocked is fake by definition. There is no real implementation behind it. It's a just a dumb implementation of an interface that returns what you tell it to return. Your code is not involved in any way. Commented Apr 29, 2020 at 9:34

4 Answers 4

1

If you want to test Calc() then test Calc(). You do not need to mock anything

[TestMethod] public void Test_Calc_DoublesProp() { //arrange var test = new Test(5); //assumes Prop value can be injected in constructor //act int result = test.Calc(); //assert Assert.IsTrue(result == 10); // 5 * 2 } 
Sign up to request clarification or add additional context in comments.

1 Comment

Again this doesn't fit the situation where I want to change my property only in my class... look here what I've just found: there is a moq framework that does that (unfortunately it is NOT free). stackoverflow.com/questions/11738102/…
1

Found a solution: Pose

It uses ILGenerator and is quite old, BUT it works.

example

var test = new Test(); // default value of 'Prop' is 0 var shim = Shim.Replace(() => test.Prop).With((Test @this) => // idk why he needs @this param { return 100; // sets the 'Prop' value to 100 }); var result = 0; PoseContext.Isolate(() => { result = test.Calc(); // prints 200; }, shim); 

2 Comments

That would be a solution to overcome the "private" issue. Note about the parameter : you don't need it, so you can probably replace @this by _ or even replace the whole (Test @this) by _
@Pac0 I actually tried it before posting, but it throws an error ... idk why? Maybe a bug or something else. The project isn't being maintained so I could imagine, that it is a bug.
0

Mocks are to be used as replacement for dependencies around what you are trying to test.

Concerning your test, just test the actual exposed behavior of your class, meaning don't try to use private methods and setters. In any case, mokcing the class to test is not a valid approach.

For instance :

If you want to test the Test class :

[TestClass] public class TestTests { [TestMethod] public void Calc_WhenPropIsSetTo5_Returns10() { /** * Seems this is what you want to test (see name of methods), * and I don't think it is a good idea, as your setter is private. * Since it's not a "public" behavior, you could either * * a) have the setter as internal for testing purposes, * * b) (my recommendation) go for the two other tests below instead; * this will actually test the exposed behavior of the class. * * c) circumvent the accessibility (by using a library or using * Reflection directly) to set the value of the prop. * See your own answer for an example. */ } [TestMethod] public void Calc_WhenCreatedWith5_Returns10() { // Arrange var testSubject = new Test(5); // if the prop is set by constructor... otherwise arrange in the proper way. // Act var actualResult = testSubject.Calc(); // Assert Assert.AreEqual(expected: 10, actualResult) } [TestMethod] public void Prop_WhenCreatedWith5_IsSetTo5() { // Arrange var testSubject = new Test(5); // Act var actualResult = testSubject.Prop; // Assert Assert.AreEqual(expected: 5, actualResult) } } 

If you want to test something that uses ITest.Calc(),

then you should, in your actual code,

1 - depend on the interface ITest, not on implementation Test

2 - have the dependency injected to the class being tested, so that you can replace the usual implementation Test by Mock<ITest>.Object()

public class ClassThatUsesTest { private readonly ITest _test; public ClassThatUsesTest(ITest test) { _test = test; } public int SomeFunction() { if (_test.Calc() == 10) { return 42; } else { return 0; } } } [TestClass] public class ClassThatUsesTestTests { [TestMethod] public void SomeFunction_WhenTestCalcReturns10_Returns42() { // Arrange var testMock = new Mock<ITest>(); testMock.Setup(x => x.Calc()).Returns(10); var testSubject = new ClassThatUsesTest(testMock.Object); var expectedResult = 42; // Act var actualResult = testSubject.SomeFunction(); // Assert.AreEqual(expectedResult, actualResult); } } 

In the last example, you can see the mocks help us to isolate the test without depending on the actual implementation details of the Test class. Even if suddenly the actual Test is broken or change (e.g. you need to pass 6 instead of 5 to get 10), the test method doesn't care.

Comments

-1

Though this feels not right as it changes method implementation for testing purpose, just for the sake of sharing:

public class Test : ITest { private int _prop; public int Prop { get => ((ITest)this).Prop; private set => _prop = value; } public int Calc() { return Prop * 2; } int ITest.Prop => _prop; } 

In test:

var mock = new Mock<Test>(); mock.As<ITest>() .Setup(x => x.Prop) .Returns(3); // This should return 6 mock.Object.Calc(); 

3 Comments

nice example, however I don't think that this is much more 'cleaner' than using reflections e.g. (PropertyInfo)
I agree :) It is just an example I guess.
@Hrant take a look at PrivateObject if you are using MSTest.