我正在尝试测试下面的函数以获取将使用关系谓词桶的所有活动类别。初始化程序类中的模拟数据添加了三个活动且未删除的对象。它在结尾添加了第四个,它被删除但没有激活。
在测试期间,调用将返回所有四个对象,而不是预期的三个对象。这是我坚持的地方。
我尝试将_randomCategories
作为Queryable对象,但这也失败了。
第一类中有很多代码,因此可能很难遵循,因此每个部分都会分成区域,说明它执行哪个部分,即测试设置,模拟数据,和测试本身。
模拟数据区域是预期的结果。对于我的需求可能没有必要,因为除了获得预期的计数之外,它不用于此,但它可能与测试的整体结构有关。
CategoryServiceTests.cs
#region Test Setup
public class CategoryServiceFixture : IDisposable
{
public CategoryService Sut { get; private set; }
private SystemRepository SystemRepository { get; set; }
private Mock<CategoryRepository> _categoryRepositoryMock;
private List<CategoryEntity> _randomCategories;
public CategoryServiceFixture()
{
// Init Category List
_randomCategories = CategoryEntityInitializer.GetAllMockCategories();
// Init repository
_categoryRepositoryMock = new Mock<CategoryRepository>(new object[] { null });
// Setup mocking behavior
// BaseRepository
_categoryRepositoryMock
.Setup(m => m.GetAll(It.IsAny<IRelationPredicateBucket>(), It.IsAny<IDataAccessAdapter>()))
.Returns(_randomCategories);
SystemRepository = new SystemRepository(category: _categoryRepositoryMock.Object);
Sut = new CategoryService(this.SystemRepository);
}
public void Dispose()
{
//Sut.Dispose();
}
}
[CollectionDefinition("CategoryService Collection")]
public class CategoryServiceCollection : ICollectionFixture<CategoryServiceFixture> { }
#endregion
#region Mock Data
public static class CategoryRepositoryMockData
{
public static IEnumerable<object> GetCategories
{
get
{
yield return new object[] { 1, new List<CategoryEntity>() {
new CategoryEntity
{
CategoryId = 1,
Name = "Test1",
IsDeleted = false,
IsActive = true
},
new CategoryEntity
{
CategoryId = 2,
Name = "Test2",
IsDeleted = false,
IsActive = true
},
new CategoryEntity
{
CategoryId = 3,
Name = "Test3",
IsDeleted = false,
IsActive = true
}
}};
}
}
}
#endregion
#region Tests
[Collection("CategoryService Collection")]
public class CategoryServiceTests
{
private CategoryServiceFixture _fixture;
public CategoryServiceTests(CategoryServiceFixture fixture)
{
_fixture = fixture;
}
[Theory]
[Trait("Category", "Get All Active Categories")]
[Trait("Expected", "Return Correct")]
[MemberData("GetCategories", MemberType = typeof(CategoryRepositoryMockData))]
public void GetActiveCategories_ShouldReturn(int id, IList<CategoryEntity> expectedCategoryObjects)
{
var result = _fixture.Sut.GetActiveCategories();
Assert.Equal(expectedCategoryObjects.Count, result.Count);
}
}
#endregion
此类生成模拟数据库对象。这是应该搜索的内容,并从列表中选择正确的。
CategoryEntityInitializer.cs
public static class CategoryEntityInitializer
{
public static List<CategoryEntity> GetAllMockCategories()
{
List<CategoryEntity> _categories = new List<CategoryEntity>();
for (var i = 1; i <= 3; i++)
{
var entity = new CategoryEntity()
{
CategoryId = i,
Name = String.Format("{0}{1}", "Test", i),
IsDeleted = false,
IsActive = true
};
_categories.Add(entity);
}
var lastEntity = new CategoryEntity()
{
CategoryId = 4,
Name = String.Format("{0}{1}", "Test", 4),
IsDeleted = true,
IsActive = false
};
_categories.Add(lastEntity);
return _categories;
}
}
这个类是谓词所在的位置。
CategoryService.cs
public class CategoryService : BaseService
{
public IList<CategoryModel> GetActiveCategories()
{
var bucket = new RelationPredicateBucket();
bucket.PredicateExpression.Add(CategoryFields.IsDeleted == false);
bucket.PredicateExpression.Add(CategoryFields.IsActive == true);
var categoriesEntities = _systemRepository.Category.GetAll(bucket);
return CategoryMapper.MapToModels(categoriesEntities);
}
}
其余代码结构适用于所有其他测试以及不同的测试类。这是我第一次不得不测试关系谓词桶。
答案 0 :(得分:0)
更新18/05/16
我找到了问题的解决方案。回答以下代码。
_categoryRepositoryMock
.Setup(m => m.GetAll(It.IsAny<IRelationPredicateBucket>(), It.IsAny<IDataAccessAdapter>()))
.Returns(new Func<IRelationPredicateBucket, IDataAccessAdapter, IEnumerable<CategoryEntity>>(
(bucket, adapter) => _randomCategories.Where(a => a.IsDeleted == false && a.IsActive == true)));
旧答案11/05/16
我相信我找到了部分答案。在模拟存储库时,无论谓词桶是否有效,我都会返回所有四个对象。
_categoryRepositoryMock
.Setup(m => m.GetAll(It.IsAny<IRelationPredicateBucket>(), It.IsAny<IDataAccessAdapter>()))
.Returns(_randomCategories);
这将导致它返回所有四个,因为我没有实现桶来过滤掉匹配。我认为.Returns
会将数据放入存储库,就像从数据库返回一样,然后使用存储桶进行过滤。
我发现对存储库的调用不会转到它正常运行时的调用,而是转到模拟的存储库,这是您需要过滤要返回的数据的地方。
需要做类似的事情。
_categoryRepositoryMock
.Setup(m => m.GetAll(It.IsAny<IRelationPredicateBucket>(), It.IsAny<IDataAccessAdapter>()))
.Returns(
(IRelationPredicateBucket bucket) => _randomCategories.Where(x => x.Name.Equals(bucket)));
虽然这仍然给我一个问题,因为我不知道如何进入桶中以匹配列表,但它至少朝着正确的方向前进。
注意:我还从搜索中发现,这种类型的失败的另一个原因是由于代码,在这种情况下,被调用的函数太复杂而无法测试。它应该分成较小的卡盘,使其不那么复杂,并单独测试每个部件。
<强>之前强>
public class CategoryService : BaseService
{
public IList<CategoryModel> GetActiveCategories()
{
var bucket = new RelationPredicateBucket();
bucket.PredicateExpression.Add(CategoryFields.IsDeleted == false);
bucket.PredicateExpression.Add(CategoryFields.IsActive == true);
var categoriesEntities = _systemRepository.Category.GetAll(bucket);
return CategoryMapper.MapToModels(categoriesEntities);
}
}
<强>后强>
public class CategoryService : BaseService
{
public IList<CategoryModel> GetActiveCategories()
{
var bucket = GetActiveCategoriesBucket();
var categoriesEntities = _systemRepository.Category.GetAll(bucket);
return CategoryMapper.MapToModels(categoriesEntities);
}
public RelationPredicateBucket GetActiveCategoriesBucket()
{
var bucket = new RelationPredicateBucket();
bucket.PredicateExpression.Add(CategoryFields.IsDeleted == false);
bucket.PredicateExpression.Add(CategoryFields.IsActive == true);
return bucket;
}
}