С# Mocking Интерфейсные элементы конкретного класса с Moq

У меня есть интерфейс ITransaction следующим образом:

public interface ITransaction {

        DateTime EntryTime { get; }

        DateTime ExitTime { get; }
}

и у меня есть производный класс PaymentTransaction следующим образом:

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
}

Я хотел бы Mock все три свойства объекта PaymentTransaction.

Я пробовал следующее, но он не работает:

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); 

но когда я вставляю

(mockedTxn.Object как PaymentTransaction)

в методе, который я тестирую (поскольку он принимает только PaymentTransaction, а не ITransaction, я не могу его изменить), отладчик показывает нулевую ссылку для времени входа и выхода.

Мне было интересно, может ли кто-нибудь помочь мне.

Спасибо в ожидании.

Ответ 1

Единственные способы, с помощью которых я мог обойти эту проблему (и это похоже на хак в любом случае) - либо делать то, что вы не хотите делать, а сделать свойства на конкретном классе виртуальными (даже для реализация интерфейса), а также явно реализовать интерфейс в вашем классе. Например:

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

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

Затем, когда вы создаете свой макет, вы можете использовать синтаксис As<ITransaction>(), и макет будет вести себя так, как вы ожидаете.

Ответ 2

Вы издеваетесь над конкретным классом, поэтому, я думаю, вы сможете только высмеять членов, которые являются виртуальными (они должны быть переопределяемыми).