Mock abstract class default behaviour with Rhino

2019-02-25 05:59发布

I'm pretty new to mocking so this might be something I'm just not picking up on yet, but I can't find a good example anywhere.

I'm trying to assert that by default, any class that inherits from my abstract class will instantiate a collection in the constructor. Here's the abstract class:

public abstract class DataCollectionWorkflow : SequentialWorkflowActivity
{
        private readonly DataSet _output = new DataSet();
        private List<DataCollectionParameter> _params = null;

        public DataCollectionWorkflow()
        {
            _params = new List<DataCollectionParameter>();   
        }

        public virtual IList<DataCollectionParameter> Parameters
        {
            get { return _params; }
            set { _params = (List<DataCollectionParameter>)value; }
        }
}

How do I mock this with Rhino? If I do a GenerateMock<DataCollectionWorkflow> (or a stub), the constructor runs and the mock's private field "_params" gets initialized, but the mock's "Parameters" property is simply null.

Obviously the generated mock subclass is overriding the property implementation. Is there some way of excluding the Parameters property from being re-implemented?

Thanks.

2条回答
来,给爷笑一个
2楼-- · 2019-02-25 06:33

Try making _params virtual

查看更多
甜甜的少女心
3楼-- · 2019-02-25 06:37

Okay, I figured it out. Chalk me up as another casualty to the intricacies of Rhino. This kind of thing makes me want to move to a simpler framework, maybe I'll check out MoQ.

So the answer is using PartialMocks. I had briefly toyed with generating a partial mock, but when I ran the debugger over it I noticed that the properties weren't even null, they were throwing weird exceptions, so I didn't look much deeper. I was using the short form AAA type of syntax.

Turns out if I simply put the mock into playback mode, the test works - the properties are used as is (as they should be with a partial mock).

So here's the answer:

[Test]
public void ShouldCreateParameterListInConstructor()
{
      var mockRepository = new MockRepository();
      var mock = mockRepository.PartialMock<DataCollectionWorkflow>();
      using ( mockRepository.Record() )
      {

      }
      using (mockRepository.Playback())
      {
           Assert.That(mock.Parameters, Is.Not.Null, "DataCollectionWorkflow base class didn't create new param collection");
      }
}

I realize that this is a stateful test but it's actually a simpler prelude to some behavioural testing that involves the property in question, so I wanted this case as prerequisite. Hope it helps someone.

查看更多
登录 后发表回答