chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
Does anyone know the best way to go about mocking private constructors? Preferably with natural typemocks.

In our system the method for creating a Coupon and saving it to the database looks as follows:

public class Coupon

        private string _couponName;

        private Coupon()

        public static Coupon Create(IDataElephant elephant, string couponName)
            Coupon coupon = new Coupon();
            coupon._couponName = couponName;
            Check.Ensure(coupon.ID != 0);
            return coupon;

The thing we want to mock in the code above is IDataElephant elephant.
Our current (not working) approach for mocking the IDataElephant in the Coupon.Create method looks something like this:
        internal static void ExpectCreateCoupon(IDataElephant elephant, string couponName)
            int id = GenerateUniqueID();
            using (RecordExpectations recorder = RecorderManager.StartRecording())
                // This is the troublemaking line of code. 
                // The construcor is private and can't be called here.
                Coupon createdCoupon = new Coupon(); // <<< Alternative needed!


                // Save would normally give createdCoupon an id, but since that's mocked:
                recorder.VerifyMode = VerifyMode.PassIfNotCalled;
                recorder.ExpectAndReturn(createdCoupon.ID, id).RepeatAlways();
                recorder.VerifyMode = VerifyMode.Normal;


So basically what we're after is some way to expect a call to the constructor and make it return a real Coupon.
The class we want to mock is IDataElephant, not the coupon.

In a test the classes above would be called like this:
ExpectCreateCoupon(elephant, "COUPONNAME");
Coupon.Create(elephant, "COUPONNAME");

Any ideas?
asked by Rydeman (600 points)

1 Answer

0 votes

If I understand you correctly what you are trying to do is test the Coupon.Create method, by mocking the IElephantData.Save method and also mocking the Coupon.ID property call.

If this assumption is correct, you are trying to do something that Natural Mocks are not suitable for - mocking a private constructor. Which makes sense - Natural Mocks allow you to write code that would run in a natural way, and you can't do that with a private constructor.

The solution is by using reflective mocks:

1. Use MockManager.MockObject for the interface:
MockObject mockElephant = MockManager.MockObject(typeof(IDataElephant));

2. Mock the Coupon object, but without mocking the constructor:
MockObject mockCoupon = MockManager.Mock(typeof(Coupon), Constructor.NotMocked);
mockCoupon.ExpectGet("ID", idValue);

3. Call the Coupon.Create method and verify.

Let me know if this helps. If not, please explain what you are trying to test so I can give a better soloution.
answered by gilz (14.5k points)