5
\$\begingroup\$

Consider the scenario below. It covers multiple methods of my unit under test.

public class OriginalSample
{
    public bool Foo(ISomeEntity entity)
    {
        return entity.IsThatSo ? entity.IsThatSo : Bar(entity);
    }

    public bool Bar(ISomeEntity entity)
    {
        return entity.IsThatAsWell;
    }
}

[TestClass]
public class OriginalSampleTest
{
    [TestMethod]
    public void Foo_EntityWithSo_ReturnsTrue
    {
        // Arrange
        Mock<ISomeEntity> someEntityMock = new Mock<ISomeEntity>();
        mock.SetupGet(m => m.IsThatSo).Returns( false );
        mock.SetupGet(m => m.IsThatAsWell).Returns( true );

        // Act
        private bool result = _OriginalSample.Foo( someEntityMock.Object );

        // Assert
        Assert.IsTrue(result);
    }
}

However, in my production code there is a lot that I need to Mock away that is then used in more method calls. I need to find a way to test the Foo method without hitting the Bar method.

I came up with the scenario as below. However the disadvantage is that i need a interface and pass the instance in each method. I do not like this design.

Any feedback?

public interface INewSample
{
    bool Foo(ISomeEntity entity, INewSample sample);
    bool Bar(ISomeEntity entity);
}

public class NewSample : INewSample
{
    public bool Foo(ISomeEntity entity, INewSample sample)
    {
        return entity.IsThatSo ? entity.IsThatSo : sample.Bar(entity);
    }

    public bool Bar(ISomeEntity entity)
    {
        return entity.IsThatAsWell;
    }
}

[TestClass]
public class NewSampleTest
{
    [TestMethod]
    public void Foo_EntityWithSo_ReturnsTrue
    {
        // Arrange
        Mock<ISomeEntity> someEntityMock = new Mock<ISomeEntity>();
        mock.SetupGet(m => m.IsThatSo).Returns( false );

        Mock<INewSample> sampleMock = new Mock<INewSample>();
        sampleMock.Setup(m => m.Bar).Returns(false).Verify();

        // Act
        private bool result = _OriginalSample.Foo( someEntityMock.Object, sampleMock.Object );

        // Assert (that the logic tried to use the 'bar' method
        sampleMock.Verify();
    }
}
\$\endgroup\$
3
\$\begingroup\$

You can't.

You need to ask yourself why it is you want to prevent executing Bar during testing. If it is because you are worried about over-covering Bar during testing, stop worrying. If it is because your real Bar implementation is long-running, then you probably need to inject another dependency into your class, or re-factor some code into a separate helper class which can then be injected.

As long as your Foo implementation needs to call Bar, your unit tests for Foo ultimately need to as well. As long as Foo ultimately calls Bar, you cannot fully test Foo without executing Bar. You shouldn't rely on it calling Bar, but you cannot prevent it from calling Bar in your tests without intentionally crippling your test coverage.

\$\endgroup\$
  • \$\begingroup\$ +1 If Bar() takes too long to run, it's not even a unit test we're talking about. \$\endgroup\$ – s.m. May 25 '12 at 21:29
  • \$\begingroup\$ @DanLyons. In the actual production code, the Foo() method has some business logic, and then calls about 4 other Bar() methods. I have written tests for those other Bar() methods. I do not want to test whether the Bar methods are called. In that case, I think the best solution is to split the Foo method into a FooLogic that will be tested and a helper method that will call both the FooLogic and the other Bar methods. This method will contain no unit test. \$\endgroup\$ – Aphelion May 29 '12 at 6:44
  • \$\begingroup\$ Well, as I stated above, your test for the code above shouldn't care whether you call other methods or not. Just test the output against expected inputs/outputs and ignore whether or not it calls the other methods. Once you do that, you can refactor out your logic into helpers to your heart's content, though I wouldn't do so just to prevent your unit tests from executing shared code. \$\endgroup\$ – Dan Lyons May 29 '12 at 18:13
0
\$\begingroup\$

How about make Bar virtual, and mock it. Using _sampleMock.Verify(c => c.Bar(entity), Times.Once()); to assert.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.