У них есть реализация класса геометрической формы, которая выглядит примерно так:
private readonly IShapeModel _shape;
public Shape(IShapeModel shape) : base(shape)
{
_shape = shape;
}
/// <summary>
/// Specific geometry data of the shape
/// </summary>
public string GeometryData => _shape.GeometryData;
/// <summary>
/// Returns the <see cref="Geometry"/> for this shape
/// </summary>
public Geometry Geometry => Geometry.Parse(GeometryData);
Как видите, я предоставляю фигуре модель и позволяю ей возвращать объект Geometry с помощью стандартного метода Parse, предоставляемого Geometry.
Код работает отлично и возвращает пустую геометрию, если GeometryData не задано.
Теперь я хочу проверить это примерно так:
[TestMethod]
public void AccessGeometryPropertyWithNoGeometryDataSetShouldReturnEmpty()
{
var shape = new TestShapeModel {GeometryData = null};
_shapeViewModel = new Shape(shape);
var expected = Geometry.Empty;
var actual = _shapeViewModel.Geometry;
Assert.AreEqual(expected, actual);
}
Хотя проблема в том, что Geometry.Empty, похоже, возвращает новый экземпляр, который не равен результату экземпляра Parsed.
Хотя оба объекта идентичны. Я получаю такой результат: Дополнительная информация: Ошибка Assert.AreEqual. Ожидается: <>. Актуально: <>.
Когда я придумал это:
[TestMethod]
public void AccessGeometryPropertyWithNoGeometryDataSetShouldReturnEmpty()
{
var shape = new TestShapeModel {GeometryData = null};
_shapeViewModel = new Shape(shape);
Assert.IsTrue(IsEmptyGeometry(_shapeViewModel.Geometry));
}
/// <summary>
/// Check if Geometry is empty by comparing Empty Bounds.
/// </summary>
private static bool IsEmptyGeometry(Geometry geometry)
{
var result = false;
var expected = Geometry.Empty;
if (geometry != null)
{
result = (geometry.Bounds == expected.Bounds);
}
return result;
}
Есть ли лучший подход для решения этой проблемы? Я ожидал, что что-то в самой структуре будет сравниваться с Geometry.Empty без переопределения Equals или реализации приведенного выше кода.
2 ответа
Если Geometry не реализован вами вообще, вы можете взять свой метод IsEmptyGeometry и сделать его методом расширения и использовать его, чтобы сделать ваше Утверждение «красивым» способом.
public static class GeometryExtensions
{
public static bool IsEmpty(this Geometry geometry)
{
var result = false;
var expected = Geometry.Empty;
if (geometry != null)
{
result = (geometry.Bounds == expected.Bounds);
}
return result;
}
}
Тогда вместо этого:
[TestMethod]
public void TestEmptyGeometry()
{
var shape = new TestShapeModel { GeometryData = null };
_shapeViewModel = new Shape(shape);
var expected = Geometry.Empty;
var actual = _shapeViewModel.Geometry;
Assert.AreEqual(expected, actual);
}
Вы могли сделать это:
[TestMethod]
public void TestEmptyGeometry()
{
var shape = new TestShapeModel { GeometryData = null };
_shapeViewModel = new Shape(shape);
var actual = _shapeViewModel.Geometry;
Assert.IsTrue(actual.IsEmpty());
}
Assert.Equals использует равное сравнение между объектами, поэтому вы должны переопределить метод Equals объекта System.Object, чтобы он работал, сравнивая два объекта Geometry. Я не знаю вашей реализации геометрии, поэтому я собираюсь предположить, как работает существенное, исходя из того, что вы объяснили.
Я предполагаю, что то, что делает одну геометрию похожей на другую, - это то, что они имеют одинаковые границы. В вашем случае это должно быть сложнее, поэтому рассмотрим это на моем примере.
Вот подсказка, что делать в вашем классе Geometry.
public class Geometry
{
// I don't know what is the implementation of bounds, so
// I'm just assuming that is something comparable here.
public Rectangle Bounds { get; set; }
// Here's your definition of Geometry.Empty, from what I understood.
public static Geometry Empty
{
get
{
return new Geometry { Bounds = new Rectangle(0, 0, 0, 0) };
}
}
// Here is the key: you must override the default operators of equality
// and difference to make comparations to work, because internally it will
// use them.
public static bool operator ==(Geometry left, Geometry right)
{
if (left == null && right == null)
{
return true;
}
if (left != null && right != null)
{
return left.Bounds == right.Bounds;
}
return false;
}
public static bool operator !=(Geometry left, Geometry right)
{
if (left == null && right == null)
{
return false;
}
if (left != null && right != null)
{
return left.Bounds != right.Bounds;
}
return true;
}
// I recommend you to override Equals method of
// System.Object too. For Assert.AreEqual to work,
// actually this method will be used.
public override bool Equals(object obj)
{
var objAsGeometry = obj as Geometry;
if (obj == null)
{
return false;
}
return objAsGeometry.Bounds == this.Bounds;
}
// GetHashCode is used in some types of comparations too,
// altough not in your case with Assert.AreEqual.
// If you want to make a fully comparable object,
// be sure to override it too, with all conditions used
// to compare one Geometry object with other.
public override int GetHashCode()
{
return Bounds.GetHashCode();
}
}
Таким образом, тест, сравнивающий два объекта Geometry.Empty, должен пройти:
[TestClass]
public class GeometryTests
{
[TestMethod]
public void TestTwoEmptyGeometries()
{
var geometry1 = Geometry.Empty;
var geometry2 = Geometry.Empty;
// Pass
Assert.AreEqual(geometry1, geometry2);
}
}
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.