2010-06-04 139 views
21

我有这样一组构造函数:使用Moq来模拟构造函数?

public BusinessObjectContext() 
     : this(CloudStorageAccount.FromConfigurationSetting("DataConnectionString").TableEndpoint.ToString(), 
       CloudStorageAccount.FromConfigurationSetting("DataConnectionString").Credentials) {} 

public BusinessObjectContext(string dataConnectionString) 
     : this(CloudStorageAccount.Parse(dataConnectionString).TableEndpoint.ToString(), 
       CloudStorageAccount.Parse(dataConnectionString).Credentials) { } 

public BusinessObjectContext(String baseAddress, StorageCredentials credentials) 
     : base(baseAddress, credentials) { } 

然而,当测试/惩戒我需要的对象,而无需任何连接字符串参数。我怎么能这样做 - 最好在Moq?

这可能吗?

回答

17

听起来好像你有代码味道 - constructor is doing too much work。该文章包含针对这些场景的一组修复程序。基本上答案是只有在构造函数中执行赋值,不执行业务逻辑。

+0

Hrrm。我在这个概念中看到了这个观点。另一方面,我想屏蔽对象GenericBusinessObject的用户,从而思考数据源上下文。 如果我遵循你的论点,那么GenericBusinessObject的用户必须考虑它。这是不太吸引人的。也许没有别的办法,但是有些事情让我犹豫不决。 – 2010-06-10 13:56:40

+1

建立工厂或使用IOC Conatainer来消除用户担心数据上下文的这种需求。 – Finglas 2010-06-13 10:07:55

26
var myMockBOC = new Mock<BusinessObjectContext>(null, null); 

这将通过空值为您的两个参数。

另一种方法是创建一个仅供测试使用的内部构造函数,并使用InternalsVisibleTo来允许测试程序集使用它。不幸的是,这有一个很大的缺点,如果你签署你的程序集,Moq is unable to use the constructor。这应该在Moq的4.0版本中解决。

+6

内部构造函数的缺点是,现在您正在编写代码来支持您的单元测试。 – 2010-11-15 20:48:53

+2

我会争辩说,这是可以接受的,当有一个有目的的要求* public * API不可注射。如果你的构造函数不是简单的,并且包含商业逻辑 - 那么,正如俗话所说,你会遇到两个问题...... – womp 2010-11-25 17:49:25

+0

非常简单的解决方案!帮助了我很多! – 2013-06-05 17:00:10