Как настроить это (Moq Setup)
Я хочу проверить свою часть кода, которая возвращает пароль пользователя. Поэтому я сделал макет поставщика членства, используя Moq.
Я не думаю, что мне нужно показать вам фактический код, только часть теста.
// 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"));
Поэтому, когда я запускаю это в 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
Итак, я предполагаю, что это что-то из-за свойства, к которому я пытаюсь получить доступ. Я не уверен, как настроить его. Я не очень хорошо знаком с lambdas (и пока не смог найти учебник по ним), поэтому я не уверен, могу ли я каким-то образом расположить его по-другому, чтобы заставить его работать.
Или, если я просто полностью пропустил отметку.
Ответы
Ответ 1
Ответ в сообщении об исключении:
... Только доступ к свойствам поддерживается в промежуточных вызовах при настройке...
Попробуйте следующее:
var user = new Mock<MemberShipUser>();
user.SetupGet(x => x.PasswordQuestion).Returns("Password");
membershipMock.Setup(m => m.GetUser("test", false)).Returns(user.Object);
Ответ 2
Я предполагаю, что промежуточный вызов, на который он ссылается, таков: m.GetUser("test", false)
, за которым следует .PasswordQuestion
. В нем говорится: вы не можете использовать метод как промежуточную заглушку, а только свойство. Эта конкретная структура, похоже, поддерживает промежуточные заглушки (т.е. Строит X.Y в определении заглушки, отметьте точку), но большинство других этого не делает.
Штыри не являются волшебными, все, что они могут сделать, это перехватить ваши вызовы и подставить возвращаемый результат с предоставленным значением. В вашем случае ваш заглушка GetUser должен вернуть макет пользователя, а его PasswordQuestion будет удален, чтобы вернуть "Пароль".
Еще одна проблема с вашим кодом заключается в том, что вы прямо издеваетесь над MembershipProvider. Как большинство из насмешливых фреймворков работают, если вы издеваетесь над интерфейсом, они динамически генерируют класс, который его реализует, и когда вы издеваетесь над классом, они генерируют класс, который наследует от него и отменяет любые виртуальные методы. Однако, если метод не является виртуальным, он не может переопределить его, следовательно, смешанное поведение, которое вы можете наблюдать. Я предлагаю вам посмотреть, есть ли там интерфейс, такой как IMembershipProvider, и если да, используйте его в своем коде вместо конкретного класса.