1

I have this code:

    [TestMethod]
    public void TestMethod()
    {
        TextBox txtBox= new TextBox() { Text = "Test" };

        PrivateObject privateObj= new PrivateObject(someObject);
        var mockObj = new Mock<PrivateObject>();
        mockObj.Setup(x => x.Invoke("SomeMethod", It.IsAny<string>())).Returns(true);

        object result = privateObj.Invoke("DoSomething", txtBox, EventArgs.Empty);

        Assert.AreEqual(txtBox.Text, string.Empty);
    }

The method "DoSomething" calls "SomeMethod" method, which returns a boolean type. How can I Mock SometMetod, so that when I call it, he returns what I need?

Alex
  • 63
  • 1
  • 10

1 Answers1

1

Sorry I should have investigated you problem more thoroughly. I didn't realize that PrivateObject was an already existing class of the .NET framework.

My answer is not going to answer your problem directly but I'm leaving it here regardless. I assume you use Moq and therefore the following parts of classes are not available for mocking:

  • non-virtual members
  • static members
  • extension methods
  • any member of sealed classes
  • fields

Private members can be tested, I'm not saying it's generally wrong. Usually the need to test private members is a sign of bad code design, though.

Private methods and fields are implementation details and should not affect your class' functionality. Don't treat each method as a unit, rather do treat the class as a unit. Test your class' behavior and that it does what it should do and don't test how it does it.

object result = privateObj.Invoke("DoSomething", txtBox, EventArgs.Empty); You are calling the DoSomething method on privateObj and not on mockObj which is not setup to return what you "need".

What should your unit test achieve? Mocking behavior of your system under test is kind of contradictory because test results will not be representative for the system's actual behavior.

I guess what you could do is to extract the functionality of SomeMethod from PrivateObject into a dependecy of it, let's say IHaveSomeMethod.

public interface IHaveSomeMethod {
    bool SomeMethod();
}

public class PrivateObject {
    private IHaveSomeMethod dependency;

    public PrivateObject(???SomeObject someObject???, IHaveSomeMethod ihsm) {
        // ...
        this.iHaveSomeMethod = ihsm;
        // ...
    }

    public void DoSometing() {
        // ...
        iHaveSomeMethod.SomeMethod();
        // ...
    }
}

Then you could test like this

[TestMethod]
public void TestMethod()
{
    TextBox txtBox= new TextBox() { Text = "Test" };

    var mockObj = new Mock<IHaveSomeMethod>();
    mockObj.Setup(x => x.Invoke("SomeMethod", It.IsAny<string>())).Returns(true);

    var sut = new PrivateObject(???someObject???, mockObj.Object); // system under test
    object result = sut.Invoke("DoSomething", txtBox, EventArgs.Empty);

    Assert.AreEqual(txtBox.Text, string.Empty);
}

Michael Schnerring
  • 3,584
  • 4
  • 23
  • 53
  • That is not how [PrivateObject](https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.privateobject.aspx) works. – Nkosi Mar 13 '17 at 10:44
  • @Nkosi oh wow, that's my bad. I updated my answer, even though it doesn't directly answer OPs problem – Michael Schnerring Mar 13 '17 at 13:29