简体   繁体   English

我该如何设置(Moq设置)

[英]How do I setup this (Moq Setup)

I want to test my part of code that returns the users password question. 我想测试返回用户密码问题的代码部分。 So I have made a mockup of the Membership provider using Moq. 所以我使用Moq制作了会员提供者的模型。

I don't think I need to show you the actual code just the test part of it. 我认为我不需要向您展示实际代码只是它的测试部分。

// Arrange
var membershipMock = new Mock<MembershipProvider>();
membershipMock.Setup(m => m.GetUser("test", false).PasswordQuestion).Returns("Password");
authentication.Authenticate.Provider = membershipMock.Object;

// Act
var actual = authentication.PasswordRecoveryStep1(It.IsAny<string>());

// Assert
Assert.That(actual, Is.EqualTo("Password"));

So when I run this in Nunit I get this: 所以,当我在Nunit中运行时,我得到了这个:

Test.Controllers.AuthenticationControllerTest.Test_If_Password_Recovery_Setp1_Returns_Users_PasswordQuestion:
System.NotSupportedException : Only property accesses are supported in intermediate invocations on a setup. Unsupported expression m.GetUser("test", False).

at Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall(MethodCallExpression m)
at Moq.ExpressionVisitor.Visit(Expression exp)
at Moq.Mock.AutoMockPropertiesVisitor.VisitMemberAccess(MemberExpression m)
at Moq.ExpressionVisitor.Visit(Expression exp)
at Moq.Mock.AutoMockPropertiesVisitor.SetupMocks(Expression expression)
at Moq.Mock.GetInterceptor(LambdaExpression lambda, Mock mock)
at Moq.Mock.<>c__DisplayClass15`2.<SetupGet>b__14()
at Moq.PexProtector.Invoke[T](Func`1 function)
at Moq.Mock.SetupGet[T1,TProperty](Mock mock, Expression`1 expression)
at Moq.Mock.<>c__DisplayClass12`2.<Setup>b__11()
at Moq.PexProtector.Invoke[T](Func`1 function)
at Moq.Mock.Setup[T1,TResult](Mock mock, Expression`1 expression)
at Moq.Mock`1.Setup[TResult](Expression`1 expression)
at Test.Controllers.AuthenticationControllerTest.Test_If_Password_Recovery_Setp1_Returns_Users_PasswordQuestion() in D:\MvcApplication9\Test\Controllers\AuthenticationControllerTest.cs:line 186

So I am guessing it is something because of the property that I am trying to access. 所以我猜这是因为我试图访问的属性。 I am not sure how to set it up. 我不知道如何设置它。 I am not very good with lambdas (and have not been able to find a tutorial on them yet) so I am not sure if I could some how arrange it differently to make it work. 我对lambdas并不是很好(并且还没有找到关于它们的教程)所以我不确定我是否能够以不同的方式安排它以使它工作。

Or if I just totally missed the mark. 或者,如果我完全错过了标记。

The answer is in exception message: 答案是在异常消息中:

... Only property accesses are supported in intermediate invocations on a setup ... ...在设置的中间调用中仅支持属性访问...

Try this: 尝试这个:

var user = new Mock<MemberShipUser>();
user.SetupGet(x => x.PasswordQuestion).Returns("Password");

membershipMock.Setup(m => m.GetUser("test", false)).Returns(user.Object);

I suppose the intermediate invocation it refers to is this: m.GetUser("test", false) since it's followed by .PasswordQuestion . 我想它引用的中间调用是这样的: m.GetUser("test", false)因为它后跟.PasswordQuestion What it says is: you can't have a method used as an intermediate stub, only a property. 它的含义是:你不能将一个方法用作中间存根,只能用一个属性。 This particular framework does seem to support intermediate stubs (ie constructs XY in the stub definition, note the dot) but most others don't. 这个特定的框架似乎确实支持中间存根(即在存根定义中构造XY,注意点)但大多数其他框架不支持。

Stubs are not magic, all they can do is intercept your calls and substitute the returned result with your provided value. 存根不是魔术,他们所能做的就是拦截你的电话并用你提供的值替换返回的结果。 In your case, your stub of GetUser needs to return a mock of user , with its PasswordQuestion stubbed away to return "Password". 在您的情况下,您的GetUser存根需要返回一个用户模拟 ,其PasswordQuestion被删除以返回“密码”。

Another problem with your code is that you're mocking MembershipProvider directly. 您的代码的另一个问题是您直接嘲笑MembershipProvider。 The way most of mocking framework work, if you mock an interface, they dynamically generate a class that implements it, and when you mock a class, they generate a class that inherits from it and overrides any virtual methods. 大多数模拟框架的工作方式,如果你模拟一个接口,它们会动态生成一个实现它的类,当你模拟一个类时,它们会生成一个继承它并重写任何虚方法的类。 However, if method is not virtual it can't override it, hence the mixed behavior you may observe. 但是,如果方法不是虚拟的,则无法覆盖它,因此您可能会观察到混合行为。 I suggest you see if there's an interface like IMembershipProvider and if yes, use that in your code instead of concrete class. 我建议您看看是否有像IMembershipProvider这样的界面,如果是,请在代码中使用它而不是具体的类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM