Using Moq to determine if a method is called

后端 未结 3 1934
暗喜
暗喜 2020-11-29 02:21

It is my understanding that I can test that a method call will occur if I call a higher level method, i.e.:

public abstract class SomeClass()
{    
    publi         


        
相关标签:
3条回答
  • 2020-11-29 02:51

    No, mock testing assumes you are using certain testable design patterns, one of which is injection. In your case you would be testing SomeClass.SomeMethod and SomeOtherMethod must be implemented in another entity which needs to be interfaced.

    Your Someclass constructor would look like New(ISomeOtherClass). Then you would mock the ISomeOtherClass and set expectation on its SomeOtherMethod to be called and verify the expectation.

    0 讨论(0)
  • 2020-11-29 02:54

    You can see if a method in something you have mocked has been called by using Verify, e.g.:

    static void Main(string[] args)
    {
            Mock<ITest> mock = new Mock<ITest>();
    
            ClassBeingTested testedClass = new ClassBeingTested();
            testedClass.WorkMethod(mock.Object);
    
            mock.Verify(m => m.MethodToCheckIfCalled());
    }
    
    class ClassBeingTested
    {
        public void WorkMethod(ITest test)
        {
            //test.MethodToCheckIfCalled();
        }
    }
    
    public interface ITest
    {
        void MethodToCheckIfCalled();
    }
    

    If the line is left commented it will throw a MockException when you call Verify. If it is uncommented it will pass.

    0 讨论(0)
  • 2020-11-29 02:56

    Even though I agree that the @Paul's answer is the recommended way to go I just want to add one alternative way which is provided by moq off the self.

    Since SomeClass is abstract it is indeed mockable, but public void SomeMehod() isn't. The point is to find the way to mock and somehow invoke that method and then using CallBase propagate the call to the SomeOtherMethod(). It might sound as a hack but it is simple in essence. It could be used in the case if the proposed refactoring is not possible.

    // This class is used only for test and purpose is make SomeMethod mockable
    public abstract class DummyClass : SomeClass
    {
        public virtual void DummyMethod() => base.SomeMethod();
    }
    

    Then you could setup DummyMethod() to propagate the call by setting CallBase flag.

    //Arrange
    var mock = new Mock<DummyClass>();
    mock.Setup(m => m.DummyMethod()).CallBase();
    
    //Act
    mock.Object.SomeMethod();
    
    //Assert
    mock.Verify(m => m.SomeOtherMethod(), Times.Once);
    
    0 讨论(0)
提交回复
热议问题