[英]How to test two objects in xunit using FluentAssertions
I have a Matrix class, and another class which is using that matrix changing it a little bit.我有一个矩阵 class 和另一个 class 正在使用该矩阵稍微改变它。 I'd like to test both matrix, one from the matrix class and the other one which has been changed, so I can confirmed they're not the same.我想测试两个矩阵,一个来自矩阵 class,另一个已经改变,所以我可以确认它们不一样。
Something like this.像这样的东西。
[Fact]
public void MatrixFromMatrixIsntTheSameThanMatrixFromMineSweeper()
{
Matrix _matrix = new Matrix(4, 4);
MineSweeper mineSweeper = new MineSweeper(4, 4, 2);
mineSweeper.Matrix.Should().NotBe(_matrix);
}
The thing is that Be/NotBe
seems is using the reference from the object, so always it returns false because they're not the same.问题是Be/NotBe
似乎使用了 object 的引用,所以它总是返回 false,因为它们不一样。 I also have tried with NotBeSameAs
, NotBeEquivalentTo
.我也尝试过NotBeSameAs
, NotBeEquivalentTo
。
These are the Matrix and MineSweeper class.这些是 Matrix 和 MineSweeper class。
public struct Coordinate
{
public int X;
public int Y;
public Coordinate(int x, int y)
=> (X, Y) = (x, y);
}
public class Matrix
{
private readonly int _M, _N;
private readonly Cell[,] _matrix;
private const char InitValue = '.';
public Matrix(int m, int n)
{
(_M, _N) = (m, n);
_matrix = new Cell[m, n];
Initialize();
}
private void Initialize()
{
for (int m = 0; m < _M; m++)
for (int n = 0; n < _N; n++)
_matrix[m, n] = new Cell(InitValue);
}
public Cell At(Coordinate coordinate)
=> _matrix[coordinate.X, coordinate.Y];
public void SetMine(Coordinate coordinate)
{
_matrix[coordinate.X, coordinate.Y] = new Cell('*');
}
}
public class MineSweeper
{
private readonly int _m, _n, _numMines;
public Matrix Matrix { get; }
public MineSweeper(int m, int n, int numMines)
{
(_m, _n, _numMines) = (m, n, numMines);
Matrix = new Matrix(m, n);
SetMines();
}
private void SetMines()
{
HashSet<Coordinate> minesSet = new HashSet<Coordinate>();
Random rnd = new Random();
while (minesSet.Count != _numMines)
minesSet.Add(new Coordinate(rnd.Next(0, _m), rnd.Next(0, _n)));
foreach (Coordinate coordinate in minesSet)
Matrix.SetMine(coordinate);
}
}
Looking at your usage of tuples, you're using a recent .NET version.查看您对元组的使用情况,您使用的是最近的 .NET 版本。 This gives you access to record
, which I recommend you use for your Cell
structure.这使您可以访问record
,我建议您将其用于您的Cell
结构。
public record struct Cell (char Value);
Records come with an implied constructor and equality comparison.记录带有隐含的构造函数和相等比较。 The equality comparison is important for you, because to compare two Matrix
objects, you would need to make sure the content of their Cell[,]
are identical.相等比较对您很重要,因为要比较两个Matrix
对象,您需要确保它们的Cell[,]
的内容相同。
You now have two options:您现在有两个选择:
Works on IEnumerable
.适用于IEnumerable
。 So if you want to compare two Matrix
objects, you want to expose the contents of your Cell[,]
arrays and compare the two.因此,如果要比较两个Matrix
对象,则要公开Cell[,]
arrays 的内容并比较两者。 You use Equal()
because you want to compare the order of items.您使用Equal()
是因为您想比较项目的顺序。 Don't use BeEquivalentTo()
because it doesn't care about order.不要使用BeEquivalentTo()
因为它不关心顺序。 See here for the different enumerable comparisons .有关不同的可枚举比较,请参见此处。
public class Matrix {
...
// Expose your array as an IEnumerable
public IEnumerable<Cell> Cells => _matrix.OfType<Cell>();
}
// And compare the contents in sequence
public void Test(){
// These have 1 Mine in the same location:
Matrix m1 = new(4,4); m1.SetMine(new(1,1));
Matrix m2 = new(4,4); m2.SetMine(new(1,1));
// 1 Mine in a different location:
Matrix xx = new(4,4); xx.SetMine(new(2,2));
// Same contents in the same order
m2.Cells.Should().Equal(m1.Cells);
// Same contents different order, are NOT Equal
xx.Cells.Should().NotEqual(m1.Cells);
// But are Equivalent
xx.Cells.Should().BeEquivalentTo(m1.Cells);
}
If you want to be strict with encapsulation, and don't want to expose the contents of your Cell[,]
as public, then you're going to have to define your equality comparison between 2 Matrix
objects.如果您想严格封装,并且不想将Cell[,]
的内容公开,那么您将不得不定义 2 个Matrix
对象之间的相等比较。 This allows you to use Be()
which will call the object's Equals()
method.这允许您使用Be()
,它将调用对象的Equals()
方法。
( Here's a full fiddle of the code below) (这是下面代码的完整小提琴)
public class Matrix {
...
/* Easiest way to compare two Cell collections is to join
the chars into a string, and perform string comparison.
We could go through the two arrays and compare the contents
one by one, but a good programmer is a lazy one.
*/
public string CellsAsString() // private so the public can't see it
=> string.Concat(_matrix.OfType<Cell>().Select(c => c.Value));
/* Now Override the Equality comparison of the Object */
public override bool Equals(object other)
=> this.CellsAsString().Equals((other as Matrix)?.CellsAsString());
// Note that we can access private methods of another object
// as long as it's the same class as `this`.
}
Your comparison will now simply be:您的比较现在将是:
Matrix m1 = new(4,4); m1.SetMine(new(1,1));
Matrix m2 = new(4,4); m2.SetMine(new(1,1));
Matrix xx = new(4,4); xx.SetMine(new(2, 2));
m2.Should().Be(m1);
xx.Should().NotBe(m1);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.