联合表的单元测试没有 return 结果
Unit test doesn't return result for joined tables
我鼓励在编写单元测试时出现问题,该单元测试在连接两个表时检查函数 return 的结果是否有效。我有以下情况:
我有 2 个表,分别命名为 Folder 和 Item,Folder 可以有多个项目。他们的 DDL 如下所示:
create table Folder
( varchar(max) Name,
int User_Id,
int Id primary key
);
create table Item
( int Id primary key,
varchar(max) Data,
int User_Id,
int Folder_id foreign key Folder(Id)
}
我想从属于名称以某个前缀开头的文件夹的项目中收集所有 'data'。所以我写了下面的函数,它工作正常并且 returns 有效结果。
string GetDatas(string prefix, int userId) //_db is injected, this function is a part of a DatasProvider class
{
dynamic folder;
return _db.dbo.Item.FindAllByUser_Id(userId)
.Join(_db.dbo.Folder, out folder)
.On(_db.dbo.Item.Folder_id == folder.Id)
.Where(_db.dbo.Folder.Name.Like(prefix))
.Select(_db.dbo.Item.Data)
.ToScalarList<string>();
}
然后我编写了一个单元测试来检查函数是否正常工作,我的规范如下所示:
public class Spec
{
private static dynamic _db;
private static IList<string> result;
private const int userId = 14;
private const string validPrefix = "dd";
private const int validFolderId = 22;
private const int invalidFolderId = 33;
private static readonly List<string> validData = new List<string>()
{
"1",
"2",
"3",
"4"
};
private static readonly List<string> invalidData = new List<string>()
{
"a",
"b",
"z"
};
public class When_getting_data : Observes<DatasProvider>
{
public Establish context = () =>
{
Database.UseMockAdapter(new InMemoryAdapter());
_db = Database.Open();
_db.dbo.Folder.Insert(Id: validFolderId, User_Id: userId, Name: validPrefix + "4231142");
_db.dbo.Folder.Insert(Id: invalidFolderId, User_Id: userId, Name: "4321" + validPrefix + "4231142");
for (int i = 0; i < validData.Count; ++i)
{
_db.dbo.Item.Insert(Id: i, User_Id: userId, Folder_Id: validFolderId, Data: validData[i]);
}
for (int i = 0; i < invalidData.Count; ++i)
{
_db.dbo.Item.Insert(Id: i + validData.Count, User_Id: userId, Folder_Id: invalidFolderId, Data: invalidData[i]);
}
depends.on<dynamic>(_db);
};
private Because of = () => result = sut.GetDatas(userId, validPrefix);
private It should_return_valid_datas_count = () => result.Count.ShouldEqual(validData.Count);
private It should_return_valid_datas = () => result.ShouldContainOnly(validData);
private It should_not_return_invalid_datas = () => result.ShouldNotContain(invalidData);
}
}
但是规范失败了,因为函数 GetDatas return 结果为 0。当我调试代码时,我发现它找到了一个用户的所有项目,但是当我想获取与该项目关联的属于用户的所有文件夹名称时,我得到一个列表,其中包含有效数量的结果,但具有空值每个结果的内部.. 我应该做些额外的事情来使测试像它应该的那样工作吗?
编辑
我也尝试在数据库适配器中指定 master/detail,但它什么也没做..
var adapter = new InMemoryAdapter();
adapter.Join.Master("Folder", "Id").Detail("Item", "Folder_Id");
Database.UseMockAdapter(adapter);
我解决了我的问题,通过更改一部分代码来收集数据:
dynamic folder;
return _db.Item.FindAllByUser_Id(userId)
.Join(_db.Folder, out folder)
.On(_db.Item.Folder_Id == folder.Id)
.With(folder)
.Where(folder.Name.Like(prefix))
.Select(_db.Item.Data)
.ToScalarList<string>();
并通过在测试中指定具有关系的适配器
var adapter = new InMemoryAdapter();
adapter.Join.Master("Folder", "Id").Detail("Item", "Folder_Id");
Database.UseMockAdapter(adapter);
_db = Database.Open();
我鼓励在编写单元测试时出现问题,该单元测试在连接两个表时检查函数 return 的结果是否有效。我有以下情况: 我有 2 个表,分别命名为 Folder 和 Item,Folder 可以有多个项目。他们的 DDL 如下所示:
create table Folder
( varchar(max) Name,
int User_Id,
int Id primary key
);
create table Item
( int Id primary key,
varchar(max) Data,
int User_Id,
int Folder_id foreign key Folder(Id)
}
我想从属于名称以某个前缀开头的文件夹的项目中收集所有 'data'。所以我写了下面的函数,它工作正常并且 returns 有效结果。
string GetDatas(string prefix, int userId) //_db is injected, this function is a part of a DatasProvider class
{
dynamic folder;
return _db.dbo.Item.FindAllByUser_Id(userId)
.Join(_db.dbo.Folder, out folder)
.On(_db.dbo.Item.Folder_id == folder.Id)
.Where(_db.dbo.Folder.Name.Like(prefix))
.Select(_db.dbo.Item.Data)
.ToScalarList<string>();
}
然后我编写了一个单元测试来检查函数是否正常工作,我的规范如下所示:
public class Spec
{
private static dynamic _db;
private static IList<string> result;
private const int userId = 14;
private const string validPrefix = "dd";
private const int validFolderId = 22;
private const int invalidFolderId = 33;
private static readonly List<string> validData = new List<string>()
{
"1",
"2",
"3",
"4"
};
private static readonly List<string> invalidData = new List<string>()
{
"a",
"b",
"z"
};
public class When_getting_data : Observes<DatasProvider>
{
public Establish context = () =>
{
Database.UseMockAdapter(new InMemoryAdapter());
_db = Database.Open();
_db.dbo.Folder.Insert(Id: validFolderId, User_Id: userId, Name: validPrefix + "4231142");
_db.dbo.Folder.Insert(Id: invalidFolderId, User_Id: userId, Name: "4321" + validPrefix + "4231142");
for (int i = 0; i < validData.Count; ++i)
{
_db.dbo.Item.Insert(Id: i, User_Id: userId, Folder_Id: validFolderId, Data: validData[i]);
}
for (int i = 0; i < invalidData.Count; ++i)
{
_db.dbo.Item.Insert(Id: i + validData.Count, User_Id: userId, Folder_Id: invalidFolderId, Data: invalidData[i]);
}
depends.on<dynamic>(_db);
};
private Because of = () => result = sut.GetDatas(userId, validPrefix);
private It should_return_valid_datas_count = () => result.Count.ShouldEqual(validData.Count);
private It should_return_valid_datas = () => result.ShouldContainOnly(validData);
private It should_not_return_invalid_datas = () => result.ShouldNotContain(invalidData);
}
}
但是规范失败了,因为函数 GetDatas return 结果为 0。当我调试代码时,我发现它找到了一个用户的所有项目,但是当我想获取与该项目关联的属于用户的所有文件夹名称时,我得到一个列表,其中包含有效数量的结果,但具有空值每个结果的内部.. 我应该做些额外的事情来使测试像它应该的那样工作吗?
编辑
我也尝试在数据库适配器中指定 master/detail,但它什么也没做..
var adapter = new InMemoryAdapter();
adapter.Join.Master("Folder", "Id").Detail("Item", "Folder_Id");
Database.UseMockAdapter(adapter);
我解决了我的问题,通过更改一部分代码来收集数据:
dynamic folder;
return _db.Item.FindAllByUser_Id(userId)
.Join(_db.Folder, out folder)
.On(_db.Item.Folder_Id == folder.Id)
.With(folder)
.Where(folder.Name.Like(prefix))
.Select(_db.Item.Data)
.ToScalarList<string>();
并通过在测试中指定具有关系的适配器
var adapter = new InMemoryAdapter();
adapter.Join.Master("Folder", "Id").Detail("Item", "Folder_Id");
Database.UseMockAdapter(adapter);
_db = Database.Open();