Search code examples
c#unit-testingxunit

How to avoid or skip some private method for XUnit test?


Let's say I have written a unit test to test a public method in XUnit.

[Fact]
public void MethodA_WhenSomething_ThenReturnNull()
{
    // Code removed for brevity.

    // Assert
}

This is MethodA.

public void MethodA() {
  MethodOne();
  MethodTwo();
  MethodThree();
}

MethodOne, MethodTwo and MethodTree are all private method. Is there a way to skip a private method (ie MethodTwo) while running my unit test for MethodA? The reason I want to skip methodTwo is because methodTwo calling a stored procedure and it causes error in Xunit. But I know the stored procedure is running fine without issue, so it is okay for me to skip this method.

And the moment, I am using this way.

public void MethodA() {
  MethodOne();

  #if DEBUG == false
    MethodTwo();
  #endif

  MethodThree();
}

If there is a better way, I wish not to put If DEBUG


Solution

  • This kind of problem is typically solved via Moq.Protected.

    So, you need to change private accessor to protected at least for MethodTwo.
    But I would suggest to change all accessors to protected.

    public class SomeClass
    {
        public void MethodA()
        {
            MethodOne();
            MethodTwo();
            MethodThree();
        }
        protected void MethodOne() { ... }
        protected void MethodTwo() { ... }
        protected void MethodThree() { ... }
    }
    

    With this, the mock setup would look like this:

    using Moq.Protected;
    
    ...
    var mockSomeClass = new Mock<SomeClass>();
    
    mockSomeClass.Protected()
                 .Setup("MethodTwo")
                 .Verifiable();
    

    Additionally you can setup a Callback to write something out the test output

    const string toBeMockedMethodName = "MethodTwo";
    mockSomeClass.Protected()
                 .Setup(toBeMockedMethodName)
                 .Callback(() => TestContext.Progress.Writeline($"{toBeMockedMethodName} has been called."))
                 .Verifiable();
    

    References: