2010-05-17 175 views
14

处理接口的正确方法是使用Moq的仅暴露集属性?之前我已经添加了其他访问器,但是这已经在我的域中流失了太多,随机的throw new NotImplementedException()声明。Moq如何正确模拟设置属性

我只想做喜欢的事,很简单:

mock.VerifySet(view => view.SetOnlyValue, Times.Never());

但这产生的The property 'SetOnlyValue' has no getter

+0

我很困惑,如果编译器发现你试图在只写属性上调用getter,测试的目的是什么?我相信我在这里错过了一些东西,或许是来自OP的澄清? – 2010-05-18 08:15:02

+1

@Igor Zevaka和其他人:'view => view.SetOnlyValue'产生'属性'SetOnlyValue'没有getter'。这是因为这段代码被解释为对getter的调用。在读写情况下,'VerifySet'对表达式进行了处理,并指出所需要的是对属性设置者的期望。在只写的情况下,这会导致编译器错误。我们需要假设OP在这里并不愚蠢,也不会为自己造成工作,而是问'我怎样才能避免做额外的垃圾'。 – 2010-05-18 09:34:30

+2

哦,我明白了。所以这是关于在moq中建立一个不依赖于需要吸气剂的属性的验证,是正确的? – 2010-05-18 12:27:58

回答

18
public class Xyz 
{ 
    public virtual string AA { set{} } 
} 
public class VerifySyntax 
{ 
    [Fact] 
    public void ThisIsHow() 
    { 
     var xyz = new Mock<Xyz>(); 
     xyz.Object.AA = "bb"; 
     // Throws: 
     xyz.VerifySet(s => s.AA = It.IsAny<string>(), Times.Never()); 
    } 
} 
public class SetupSyntax 
{ 
    [Fact] 
    public void ThisIsHow() 
    { 
     var xyz = new Mock<Xyz>(); 
     xyz.SetupSet(s => s.AA = It.IsAny<string>()).Throws(new InvalidOperationException()); 
     Assert.Throws<InvalidOperationException>(() => xyz.Object.AA = "bb"); 
    } 
} 
+0

+1 - 阅读过这篇文章后,我删除了我的答案,因为它似乎是OP想要的。 – Lee 2010-05-18 09:53:29

+0

@李:酷,大(我知道我也做了一个双读取的问题呢!) – 2010-05-18 10:12:28

+0

谢谢鲁本,我从来不会随意决定把一个It.IsAny表达式放在一行,resharper说是一个编译错误! – 2010-05-18 12:16:32

2

感谢鲁本编译错误!

并帮助有人用VB.Net疑难杂症,这是在VB.Net相同的代码:

Public Interface Xyz 
    WriteOnly Property AA As String 
End Interface 
Public Class VerifySyntax 
    <Fact()> 
    Public Sub ThisIsHow() 
     Dim xyz = New Mock(Of Xyz) 
     xyz.Object.AA = "bb" 
     ' Throws: 
     xyz.VerifySet(Sub(s) s.AA = It.IsAny(Of String)(), Times.Never()) 
    End Sub 
End Class 
Public Class SetupSyntax 
    <Fact()> 
    Public Sub ThisIsHow() 
     Dim xyz = New Mock(Of Xyz) 
     xyz.SetupSet(Sub(s) s.AA = It.IsAny(Of String)()).Throws(New InvalidOperationException()) 
     Assert.Throws(Of InvalidOperationException)(Sub() xyz.Object.AA = "bb") 
    End Sub 
End Class 

这里重要的是,你不能使用单行功能 lambda,因为这将被解释为返回值的表达式,而不是您之后的赋值语句。 这是因为VB.Net使用单等号不仅为分配也为相等比较,所以尝试做

 xyz.VerifySet(Function(s) s.AA = It.IsAny(Of String)(), Times.Never()) 

将被解释为s.AA值和一个布尔比较It.IsAny(Of String)(),从而调用getter,这将再次导致编译错误。 相反,您希望使用Sub lambda(或可能是多行函数lambda)。

但是,如果您在属性上有getter,函数lambda仍然可以工作。