实现获取和设置的模拟对象未在接口中定义

时间:2011-06-06 16:32:43

标签: mocking moq rhino-mocks

使用Moq,RhinoMocks或类似的框架,是否有一种方法可以配置一个模拟来实现对象的所有属性的get和set,即使接口没有?

我当然可以手动模拟对象,但更喜欢使用像Moq或RhinoMocks这样的隔离框架来避免创建一堆样板类。

以下是一些示例代码:

//interface to be mocked
public interface IMyObject
{
    string Property1 { set; }
}

//test method code
var mock = Moq.Mock<IMyObject>();

//...some code here to configure all properties on mock to have a get and set...

var mockObject = mock.Object;

ClassUnderTest obj = new ClassUnderTest(mockObject);
obj.MethodUnderTest();

Assert.IsTrue(!String.IsNullOrEmpty(mockObject.Property1));    

按原样运行代码会在mockObject.Property1上抛出异常,因为IMyObject.Property1属性缺少get访问器。

谢谢,DanO

4 个答案:

答案 0 :(得分:4)

public class Test
{
    public void AssertOneElement()
    {
        var mock = new Mock<IMyObject>();
        var list = default(IList<int>);

        mock.SetupSet(x => x.Property1 = It.IsAny<IList<int>>())
            .Callback<IList<int>>(value => list = value);

        // Fails
        mock.Object.Property1 = new List<int>();

        // Succeeds
        // mock.Object.Property1 = new List<int>(new[] { 1 });

        Debug.Assert(list != null);
        Debug.Assert(list.Count == 1, "Called with a list that did not contain a single element!");
    }
}

public interface IMyObject
{
    IList<int> Property1 { set; }
}

答案 1 :(得分:1)

使用Rhino Mocks,您可以为该属性设置期望值。这基本上表明您希望将属性设置为某个值。使用您的示例,示例测试方法体将是:

    var mock = MockRepository.GenerateMock();     mock.Expect(x =&gt; x.Property1 =“Test”);

var classUnderTest = new ClassUnderTest(mock);
classUnderTest.MethodUnderTest();

mock.VerifyAllExpectations();

这会检查Property1是否在调用mock.Expect和调用mock.MethodUnderTest之间的某个时间点设置为“测试”(技术上,Property1可以在ClassUnderTest)的构造函数中设置。

为了测试该属性是否已设置并忽略它实际设置的内容,只需将IgnoreArguments链接到Expect调用的返回,如下所示:

    mock.Expect(x =&gt; x.Property1 =“Test1”)。IgnoreArguments();

测试更复杂的只写属性的一种方法是使用GetArgumentsForCallsMadeOn方法。这允许您检索传递给属性的每个“调用”的参数列表。执行此操作的代码如下所示:

    var mock = MockRepository.GenerateMock();

var classUnderTest = new ClassUnderTest(mock);
classUnderTest.MethodUnderTest();

//the argument in the Action is ignored, so just use null
//Property1 is of type List<string>
var arguments = mock.GetArgumentsForCallsMadeOn(x => x.Property1 = null);

//arguments[0] contains the list of arguments for the first "call" of the
//property the first index (0) of that would contain the first argument
var firstCallArguments = arguments[0];
var firstArgument = (List<string>)firstCallArguments[0];
Assert.AreEqual(3, firstArgument.Count);

我确信Moq具有类似的功能,如果你想使用它,而不是。

答案 2 :(得分:1)

使用Moq,这有效:

var mock = new Mock<IMyObject>();

// test code goes here

// Note single equals sign, not double equals
mock.VerifySet(x => x.Property1 = "expected");

SetupAllProperties不起作用。

答案 3 :(得分:1)

列表:

var mock = new Mock<IMyObject>();

// your test code

mock.VerifySet(x => x.Property1 = It.Is<IList<int>>(l => l != null && l.Count > 0));