How to write unit test for private method in c# using moq framework?

匆匆过客 提交于 2019-12-04 23:13:10

You can't, at least not with Moq.

But more importantly, you shouldn't. First off, you don't test methods, you test behaviours. Second, in order to test behaviours, you exercise a type's public API and verify the outcomes of that exercise.

Private methods are implementation details. You don't want to verify how things get done, you want to verify that things do get done.

Grinn

Perhaps you shouldn't (see other answers for why), but you can do this using Microsoft's Visual Studio Test Tools. A simplified example is given below.

Given the following class which you want to test:

public class ClassToTest
{
    private int Duplicate(int n)
    {
        return n*2;
    }
}

You can use the following code to test the private Duplicate method:

using Microsoft.VisualStudio.TestTools.UnitTesting;

// ...

[TestMethod]
public void MyTestMethod()
{
    // Arrange
    var testClass = new ClassToTest();
    var privateObject = new PrivateObject(testClass);

    // Act
    var output = (int) privateObject.Invoke("Duplicate", 21);

    // Assert
    Assert.AreEqual(42, output);
}

In the AssemblyInfo.cs of your project add

[assembly: InternalsVisibleTo("Namespace.OfYourUnitTest.Project")]

then you make the method internal instead of private.

It has the benefit of avoiding to make it public.

However as pointed by dcastro, some people strongly disagree with this way of testing.

Liath

Simply, you don't. Private methods are not visible to other classes.

There are a number of ways around this:

  • Treat the private as part of the method you're testing, cover it in their unit tests. Think of the public methods as black boxes and test their operations.
  • Make it protected and inherit your test class from the class you're testing (or use a partial - same idea)
  • Make it public (which if you're coding to an interface doesn't actually expose it to your consumers)

For public methods (option three) it is possible to partial mock the class where you can replace the method. In Moq you can do this like this:

var moq = new Mock<MyClass>();
moq.CallBase = true;
moq.Setup(x => x.MyPublicMethodToOverride()).Returns(true);

There are more details here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!