Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# Mocking Interface members of a concrete class with Moq

I have an interface ITransaction as follows:

public interface ITransaction {

        DateTime EntryTime { get; }

        DateTime ExitTime { get; }
}

and I have a derived class PaymentTransaction as follows:

public class PaymentTransaction : ITransaction {

        public virtual DateTime LastPaymentTime
        {
            get { return DateTime.Now; }
        }

        #region ITransaction Members

        public DateTime EntryTime
        {
            get  { throw new NotImplementedException(); }
        }

        public DateTime ExitTime
        {
            get  { throw new NotImplementedException(); }
        }

        #endregion
}

I wanted to Mock all three properties of PaymentTransaction Object.

I have tried the following, but it doesnt work:

var mockedPayTxn = new Mock<PaymentTransaction>();
mockedPayTxn.SetUp(pt => pt.LastPaymentTime).Returns(DateTime.Now); // This works

var mockedTxn = mockedPayTxn.As<ITransaction>();
mockedTxn.SetUp(t => t.EntryTime).Returns(DateTime.Today); 
mockedTxn.SetUp(t => t.ExitTime).Returns(DateTime.Today); 

but when I inject

(mockedTxn.Object as PaymentTransaction)

in the method I am testing (as it is only takes a PaymentTransaction and not ITransaction, I can't change it either) the debugger shows null reference for entry time and exit time.

I was wondering if someone could help me please.

Thanks in anticipation.

like image 612
Raghu Avatar asked Jan 15 '10 03:01

Raghu


2 Answers

The only ways I have been able to get around this issue (and it feels like a hack either way) is to either do what you don't want to do and make the properties on the concrete class virtual (even for the interface implementation), or to also explicitly implement the interface on your class. For instance:

public DateTime EntryTime
{
  get  { return ((ITransaction)this).EntryTime; }
}

DateTime ITransaction.EntryTime
{
  get { throw new NotImplementedException(); }
}

Then, when you create your Mock, you can use the As<ITransaction>() syntax and the mock will behave as you expect.

like image 78
mkedobbs Avatar answered Oct 14 '22 18:10

mkedobbs


You're mocking a concrete class, so I guess you'll only be able to mock members that are virtual (they must be overridable).

like image 30
lesscode Avatar answered Oct 14 '22 16:10

lesscode