如何使用 FluentAssertions 在 xunit 中测试两个对象
How to test two objects in xunit using FluentAssertions
我有一个矩阵 class,另一个 class 正在使用该矩阵稍微改变它。我想测试两个矩阵,一个来自矩阵 class,另一个来自矩阵 class,另一个已经改变,所以我可以确认它们不一样。
类似这样。
[Fact]
public void MatrixFromMatrixIsntTheSameThanMatrixFromMineSweeper()
{
Matrix _matrix = new Matrix(4, 4);
MineSweeper mineSweeper = new MineSweeper(4, 4, 2);
mineSweeper.Matrix.Should().NotBe(_matrix);
}
问题是 Be/NotBe
似乎正在使用对象的引用,所以总是 returns false 因为它们不一样。我也试过 NotBeSameAs
, NotBeEquivalentTo
.
这些是 Matrix 和 MineSweeper class。
矩阵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('*');
}
}
扫雷Class
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);
}
}
查看您对元组的使用情况,您使用的是最新的 .NET 版本。这使您可以访问 record
,我建议您将其用于 Cell
结构。
public record struct Cell (char Value);
记录带有隐含的构造函数和相等性比较。相等比较对您很重要,因为要比较两个 Matrix
对象,您需要确保它们 Cell[,]
的内容相同。
您现在有两个选择:
1。应该()。等于()
适用于 IEnumerable
。所以如果你想比较两个 Matrix
对象,你想公开你的 Cell[,]
数组的内容并比较两者。您使用 Equal()
是因为您想要比较项目的顺序。不要使用 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);
}
2。应该().Be()
如果你想严格封装,并且不想将 Cell[,]
的内容公开为 public,那么你将不得不定义你的相等比较2 Matrix
个对象。这允许您使用 Be()
来调用对象的 Equals()
方法。
(下面代码的Here's a full fiddle)
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.
*/
private 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`.
}
您的比较现在将是:
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);
通常我们推荐 BeEquivalentTo
,但由于您的 Matrix
class 不公开任何 public 字段或属性,唯一的其他选择是 NPras 在选项 2 中建议。
我有一个矩阵 class,另一个 class 正在使用该矩阵稍微改变它。我想测试两个矩阵,一个来自矩阵 class,另一个来自矩阵 class,另一个已经改变,所以我可以确认它们不一样。
类似这样。
[Fact]
public void MatrixFromMatrixIsntTheSameThanMatrixFromMineSweeper()
{
Matrix _matrix = new Matrix(4, 4);
MineSweeper mineSweeper = new MineSweeper(4, 4, 2);
mineSweeper.Matrix.Should().NotBe(_matrix);
}
问题是 Be/NotBe
似乎正在使用对象的引用,所以总是 returns false 因为它们不一样。我也试过 NotBeSameAs
, NotBeEquivalentTo
.
这些是 Matrix 和 MineSweeper class。
矩阵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('*');
}
}
扫雷Class
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);
}
}
查看您对元组的使用情况,您使用的是最新的 .NET 版本。这使您可以访问 record
,我建议您将其用于 Cell
结构。
public record struct Cell (char Value);
记录带有隐含的构造函数和相等性比较。相等比较对您很重要,因为要比较两个 Matrix
对象,您需要确保它们 Cell[,]
的内容相同。
您现在有两个选择:
1。应该()。等于()
适用于 IEnumerable
。所以如果你想比较两个 Matrix
对象,你想公开你的 Cell[,]
数组的内容并比较两者。您使用 Equal()
是因为您想要比较项目的顺序。不要使用 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);
}
2。应该().Be()
如果你想严格封装,并且不想将 Cell[,]
的内容公开为 public,那么你将不得不定义你的相等比较2 Matrix
个对象。这允许您使用 Be()
来调用对象的 Equals()
方法。
(下面代码的Here's a full fiddle)
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.
*/
private 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`.
}
您的比较现在将是:
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);
通常我们推荐 BeEquivalentTo
,但由于您的 Matrix
class 不公开任何 public 字段或属性,唯一的其他选择是 NPras 在选项 2 中建议。