代码改变世界

What is “Mock You”系列之(四):自定义Mock对象行为 & MockFactory

2010-02-21 17:16  姜 萌@cnblogs  阅读(1376)  评论(0编辑  收藏  举报

何谓Mock对象行为?

由于模拟出的对象终究是用来“糊弄人”的。我们在UnitTest中不一定会将一个对象的所有方法都Mock掉。而且如果一个Mock对象中有还有用接口/抽象类表示的对象,那么我们不一定就要将它们一起Mock掉。Moq为我们提供了自定义配置这些细节规则的办法。

MockBehavior

Moq有个枚举类型MockBehavior,有三个值Strict,Loose,Default。

Strict表示Mock对象在调用一个方法前这个方法必须被Mock掉,否则就会引发MockException。

而Loose与之相反,如果调用没有Mock的方法也不会出错。Default默认为Loose。

具体的设置方法是在new一个Mock<T>的时候。要注意Mock<T>中的Behavior属性是只读的。

[TestMethod]
        [ExpectedException(typeof(MockException))]
        public void MoqTest4()
        {
            var mo = new Mock<TargetInterfaceOne>(
                MockBehavior.Strict/*如果设置为Loose则不会引发异常,当前默认为Loose*/
                );//还有要注意的是Mock.Behavior是只读属性,所以只能在构造方法中设置
            mo.Object.MethodPure();//在MockBehavior.Strict设置下,一切调用未填充的方法/属性/事件时会抛出异常
        }

DefaultValue

我们再添加一个接口TargetInterfaceTwo用来演示DefaultValue在不同设定下Mock对象的不同行为。代码如下:

[TestMethod]
        [ExpectedException(typeof(NullReferenceException))]
        public void MoqTest5()
        {
            var mo = new Mock<TargetInterfaceTwo>
            {
                DefaultValue = DefaultValue.Mock/*如果设置为DefaultValue.Mock就不会引发异常,没有引用的成员会被自动Mock*/
            };

            mo.Object.one.MethodPure();
            /*var inner_mo = Mock.Get(mo.Object.one);Mock.Get可以用于获得其中自动Mock的对象实例,然后再对其进一步操作*/
        }

public interface TargetInterfaceTwo
        {
            TargetInterfaceOne one { get; set; }
            void Two();
        }

这里注意Mock类(一个抽象类)有一个静态方法Get<T>(T mock),如果Mock对象是被自动创建的,我们可以用它来获得这个Mock对象。

MockFactory

通过MockFactory我们可以批量生产我们自定义配置的Mock对象,并通过MockFactory.Verify/VerifyAlll来统一验证。示例如下。

[TestMethod]
        public void MoqTest6()
        {
            MockFactory mf = new MockFactory(MockBehavior.Loose) { DefaultValue = DefaultValue.Mock };
            var mo = mf.Create<TargetInterfaceOne>();
            var mo2 = mf.Create<TargetInterfaceOne>();
            mo.Setup(p => p.MethodPure()).Verifiable("must be invoked");
            mo2.Setup(p => p.MethodPure());
            mf.Verify();
        }