How to mock private fields?

79 views
Skip to first unread message

Hui Zhao

unread,
Dec 7, 2015, 10:29:37 AM12/7/15
to Moq Discussions
I have the code.

 public class CancellationAuthorization
    {
        private readonly string _authCode;
        private readonly FundsTransferInfo _fundsTransferInfo;
        public CancellationAuthorization(string authCode,FundsTransferInfo fundsTransferInfo)
        {
            _authCode = authCode;
            _fundsTransferInfo = fundsTransferInfo;
        }

        public virtual ChargeAuthorizationObject CancelAuthorization()
        {
            var transfer = new AccountTransfer(_fundsTransferInfo);
            return transfer.CancelBalanceTransfer(_authCode);
        }
    }

Then in my test code, I have uncompleted code.
 [Theory]
        [MemberData("TestData")]
        public void CancelAuthorization_Should_Cancel_Transaction(FundsTransferInfo fundsTransferInfo,string authCode)
        {
            // ARRANGE
            var cancelAuthorizationMock = new Mock<CancellationAuthorization>(It.IsAny<string>(),It.IsAny<FundsTransferInfo>()) {CallBase = true};
            var cancelAuthorization = cancelAuthorizationMock.Object;
           
            // ACT
            var result = cancelAuthorization.CancelAuthorization();

Not sure how to mock the private fields such as
_authCode


Ale Miralles

unread,
Dec 7, 2015, 12:00:45 PM12/7/15
to moq...@googlegroups.com
You can't. It only works for public virtual or interface members.
There is a saying that states "Every problem in object oriented languages can be solve by adding an indirection level (Except for too many indirection levels)"
So back to your case, instead of trying to mock the private field, add a method that returns the value of that private field and mock that method instead. (In fact, is's a pretty common pattern).

~ Ale Miralles.


--
--
Post: moq...@googlegroups.com
Unsubscribe: moqdisc-u...@googlegroups.com
---
You received this message because you are subscribed to the Google Groups "Moq Discussions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to moqdisc+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Hui Zhao

unread,
Dec 7, 2015, 12:46:40 PM12/7/15
to Moq Discussions
If I add a method that returns the value of that private field and mock that method instead. I have virtual member call in constructor warned by ReSharper.

Ale Miralles

unread,
Dec 7, 2015, 4:38:54 PM12/7/15
to moq...@googlegroups.com
That's true, but as R# suggest, it's just a warning. I doesn't mean that is forbidden. (And you can disable that warning with a comment).
Other approach is to have a non virtual method (which is called from the constructor) that internally calls the virtual one. Admittedly, it messy, but it'll work with no warnings.

What I usually do when I have to put non trivial logic into constructors is extract the constructor code into a factory method and call that method instead. The disadvantage in this case is that in general factory methods rely on private constructors (for consistency sake) which ends up begin a complication for mocking because you can't create a mock from a class that have no public constructor.

Don'y get me wrong, calling virtual methods inside a constructor could be dangerous, but in this case, I'll just disable the warning with comment and move on.

PS: you may have seen that, but it's a good read about that R# warning.

~ Ale Miralles




Reply all
Reply to author
Forward
0 new messages