В следующем коде, почему делает mockTest. ToString () возвращают Пустой указатель?
Править: Добавленный комментарий в пример кода, чтобы показать, как решить проблему.
Public Sub Main()
Try
Dim test = New TestClass
If test.ToString <> "stackoverflow rules" Then
Throw New Exception("Real Failed: Actual value: <" + test.ToString + ">")
End If
Dim mock = New Moq.Mock(Of TestClass)()
mock.SetupGet(Function(m As TestClass) m.Name).Returns("mock value")
' As per Mark's accepted answer this is the missing line of
' of code to make the code work.
' mock.CallBase = True
Dim mockTest = DirectCast(mock.Object, TestClass)
If mockTest.ToString() <> "mock value" Then
Throw New Exception("Mock Failed: Actual value: <" + mockTest.ToString + ">")
End If
Console.WriteLine("All tests passed.")
Catch ex As Exception
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine(ex.ToString)
Console.ForegroundColor = ConsoleColor.White
End Try
Console.WriteLine()
Console.WriteLine("Finished!")
Console.ReadKey()
End Sub
Public Class TestClass
Public Sub New()
End Sub
Public Overridable ReadOnly Property Name() As String
Get
Return "stackoverflow rules"
End Get
End Property
Public Overrides Function ToString() As String
Return Me.Name
End Function
End Class
Как свойство Name, так и метод ToString на TestClass являются виртуальными/перестраиваемыми, что означает, что Moq будет насмехаться над ними.
По умолчанию, Moq возвращает ноль для членов с типом возврата ссылочного типа, если только вы явно не скажете ему возвращать что-то другое. Так как строка является типом ссылки, она возвращает ноль.
Вы можете исправить это, установив CallBase в true.
Установка CallBase в true приведет к тому, что Moq вызовет базовую реализацию, если вы явно не определите переопределение:
mock.CallBase = True
В этом случае, это даст указание подражателю использовать базовую реализацию ToString, так как никакой электронной установки не существует (и, таким образом, вызовет свойство Name, которое does имеет установку).
.Потому что вы не сказали ему вернуть что-либо другое. Вы полагаетесь на внутреннюю работу вашего метода ToString, чтобы вернуть значение свойства имени, но сам метод ToString высмеивается.
Я думаю, что вам нужно установить свойство CallBase
вашего высмеивания в true
, чтобы указать, что неожиданные вызовы метода на самом деле выполняются на базовом объекте.
Источником вопроса действительно, что вы издеваются, что вы тестируете .
Это наиболее распространенная причина этих видов вопросов. Макеты предназначены для выделения того, что вы действительно пытаетесь проверить, а не то, что вы пытаетесь проверить себя.
Вы должны проверить этот метод непосредственно и высмеивать любые зависимостей , а не объект, который вы пытаетесь проверить сам.
Единственная причина, по которой вы должны использовать частичные издевательства (какая настройка Callbase позволяет вам делать) - это если класс, с которым вы работаете, является абстрактным, и вы хотите проверить функциональность абстрактного класса, даже если у вас нет реализации классы.
Вышеупомянутое решение работает только до тех пор, пока вы не пытаетесь имитировать то, что возвращает метод ToString (). Например. если бы я использовал заглушку для вышеупомянутого класса для тестирования другого класса, мне нужно было бы указать, что он возвращает после вызова ToString (). К сожалению, даже после использования
stub.Setup (s => s.ToString ()). Returns ("fakevalue")
Moq все равно будет возвращать собственное переопределение ToString () ("CastleProxies .....") .
Если, с другой стороны, я установлю
stub.CallBase = true
;
, он также не будет использовать мою установку.
Я нашел решение не использовать ToString () полностью, а ввести свойство, например Имя, которое мои классы теперь будут использовать вместо ToString () и которое я могу легко настроить.
Чтобы сохранить функциональность ToString (), я просто использую return Name;
там.
Иногда проще сделать что-то немного отличное от обычного, чтобы избавиться от головной боли;)
Мое решение заключалось в создании фиктивного интерфейса, определяющего ToString, и добавлении метода расширения, который упрощает настройку ожиданий для ToString:
public static class MoqExtensions
{
public static ISetup<IToStringable, string> SetupToString<TMock>(this Mock<TMock> mock) where TMock : class
{
return mock.As<IToStringable>().Setup(m => m.ToString());
}
//Our dummy nested interface.
public interface IToStringable
{
/// <summary>
/// ToString.
/// </summary>
/// <returns></returns>
string ToString();
}
}
Вы затем можно использовать метод расширения следующим образом:
[Test]
public void ExpectationOnToStringIsMet()
{
var widget = new Mock<IWidget>();
widget.SetupToString().Returns("My value").Verifiable();
Assert.That(widget.Object.ToString(), Is.EqualTo("My value"));
widget.Verify();
}