Moq是一个具有内部属性并实现接口的类

时间:2015-10-26 20:30:21

标签: c# unit-testing moq

所以我有一个实现接口并具有内部属性的类。我需要使用Moq来模拟这两个方法。

public interface IMyObject
{
    bool myMethod (String input);
}

public class MyObject : IMyObject
{
    public bool myMethod(String input) {...}
    internal bool myProperty {get;}
}

现在,我可以使用Moq进行模拟。

myMethod的:

var myIObjectMock = mockRepository.Create<IMyObject>();
myIObjectMock.Setup(m => m.myMehtod(It.IsAny<String>())).Returns((String input) => {...});

myProperty的:

var myObjectMock = mockRepository.Create<MyObject>();
myObjectMock.SetupGet(m => m.myProperty).Returns(...);

我的问题是,如何模拟两者?

问题的核心似乎是我在第一种情况下嘲笑一个界面而在第二种情况下嘲笑一个类。所以我看到的解决方案就是制作它,这样你就可以通过模拟类或接口来模拟属性和方法。这意味着将内部属性切换为公共属性,并将其作为接口的一部分或使方法成为虚拟。

是否存在不涉及更改MyObject类的解决方案?

2 个答案:

答案 0 :(得分:0)

我认为不在界面上的内部属性是一个警告,因为你似乎在等待类的一些副作用来设置它可能导致竞争条件。一般来说,你应该保持你的属性不变,以避免这种困难。

你提到了解决这个问题的唯一两种方法。最不具侵入性的是使该方法成为虚拟的。添加另一个字段的另一个选择,也不是那么冒险。我只是做出其中​​一个更改并完成它。你唯一能做的就是尝试通过接口在这个类中混合一个扩展方法,我强烈建议避免使用。

答案 1 :(得分:0)

第一个警告是,如果您的类定义和单元测试在不同的程序集中,并且它们可能是,您首先必须添加

[assembly: InternalsVisibleTo("<test project name>")]

到正在测试的程序集的AssemblyInfo.cs文件中,内部属性甚至显示给单元测试程序集。

至于Moq需要两个单独的物体,你可能不会。使用上面的例子

var mock = new Mock<MyObject>();
mock.As<IMyObject>().Setup(m => m.myMethod(It.IsAny<string>())).Returns(...);
mock.SetupGet(m => m.myProperty).Returns(...);

不幸的是,该设置将抛出NotSupportedException,因为myProperty不是虚拟的,Moq不支持模拟非虚拟成员。您将不得不为这种类型的功能查看不同的模拟库。