When mocking a class with Moq, how can I CallBase for just specific methods?

前端 未结 3 1034
清歌不尽
清歌不尽 2020-12-05 22:55

I really appreciate Moq\'s Loose mocking behaviour that returns default values when no expectations are set. It\'s convenient and saves me code, and it also act

3条回答
  •  失恋的感觉
    2020-12-05 23:14

    There is a way to call the real method and have a call back when the method is void, but it's really hacky. You have to make your call back call it explicitly and trick Moq into calling the real one.

    For example, given this class

    public class MyInt
    {
        public bool CalledBlah { get; private set; }
    
        public virtual void Blah()
        {
            this.CalledBlah = true;
        }
    }
    

    You can write your test this way:

    [Test]
    public void Test_MyRealBlah()
    {
        Mock m = new Mock();
        m.CallBase = true;
    
        bool calledBlah = false;
        m.When(() => !calledBlah)
            .Setup(i => i.Blah())
            .Callback(() => { calledBlah = true; m.Object.Blah(); })
            .Verifiable();
    
        m.Object.Blah();
    
        Assert.IsTrue(m.Object.CalledBlah);
        m.VerifyAll();
    }
    

    The key aspect is that you track if the fake version has been called, and then you set the mock up to not call the fake if it's already been called.

    You can still do something similar if you take args and the value matters:

    public class MyInt
    {
        public List CalledBlahArgs { get; private set; }
    
        public MyInt()
        {
            this.CalledBlahArgs = new List();
        }
    
        public virtual void Blah(int a)
        {
            this.CalledBlahArgs.Add(a);
        }
    }
    
    [Test]
    public void Test_UpdateQueuedGroups_testmockcallback()
    {
        Mock m = new Mock();
        m.CallBase = true;
    
        List fakeBlahArgs = new List();
    
        m.Setup(i => i.Blah(It.Is(a => !fakeBlahArgs.Contains(a))))
            .Callback((a) => { fakeBlahArgs.Add(a); m.Object.Blah(a); })
            .Verifiable();
    
        m.Object.Blah(1);
    
        Assert.AreEqual(1, m.Object.CalledBlahArgs.Single());
        m.Verify(b => b.Blah(It.Is(id => 1 == id)));
    }
    

提交回复
热议问题