我使用洋葱架构和数据访问实体框架实现了存储库模式,现在我想使用Moq进行测试。我刚刚问了一个关于SO的问题,答案我现在更加困惑(答案很好,但是我对阅读doc后如何模拟的理解很差)。我想要做的是测试Repository
方法Get(long id)
。我的存储库构造函数将DbContext
作为参数(称为PrincipalServerContext
),因此建议我模拟上下文以测试我的Repository
。让我们说这是我的Repository
:
public class PrincipalServerContext : DbContext
{
public DbSet<Web_Documents> WebDoc { get; set; }
public PrincipalServerContext()
: base("name=PrincipalServerDB")
{
Database.SetInitializer(new Initializer());
}
}
现在我的一个POCO Web_Documents
(EF实体):
public class Web_Documents
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long IDDocument { get; set; }
[Required]
[MaxLength(255)]
public string NomDocument { get; set; }
[Required]
public long IDCategorie { get; set; }
[ForeignKey("IDCategorie")]
public Web_Categories cat { get; set; }
[Required]
[MaxLength(255)]
public string Lien { get; set; }
[MaxLength(50)]
public string Type { get; set; }
public virtual ICollection<Web_Profils> Profils { get; set; }
}
最后我的Repository
方法(知道存储库是通用的,我使用POCO作为通用类型):
public T Get(long id)
{
ObjectContext objContext = ((IObjectContextAdapter)context).ObjectContext;
ObjectSet<T> set = objContext.CreateObjectSet<T>();
IEnumerable<string> keyNames = set.EntitySet.ElementType
.KeyMembers
.Select(k => k.Name);
if (keyNames.Count() > 1)
return null;
else
{
string idName = keyNames.ElementAt(0); // For Document would be IDDocument
var parameter = Expression.Parameter(typeof(T));
var property = Expression.Property(parameter, idName);
var idValue = Expression.Constant(id, id.GetType());
var equal = Expression.Equal(property, idValue);
var predicate = Expression.Lambda<Func<T, bool>>(equal, parameter);
return entities.SingleOrDefault(predicate);
//Returns the corresponding entity to 'id' and 'T'
}
}
这会构建一个具有适当ID名称的表达式,因为每个表都有不同的ID名称(公司的策略)。
从我在这里被告知Should this case of Assert.AreSame return true?我明白我必须为Mock对象构建一个返回类型,但是我的上下文类很薄我没有任何方法或任何东西,只是一个DbSet。 所以我尝试了这个作为测试,但它可能没有任何意义,因为它失败了(我真的迷失了,不理解它):
Mock<PrincipalServerContext> moqContext;
public void IdExists(){
moqContext = new Mock<PrincipalServerContext>();
var set = new Mock<DbSet<Web_Documents>>();
moqContext.Setup(c => c.Set<Web_Documents>()).Returns(set.Object);
repoDoc = new Repository<Web_Documents>(moqContext.Object);
var testDoc = repoDoc.Get(1L);
Assert.AreEqual(testDoc.NomDocument, "Ajouter une catégorie");
}
说我想做一个简单的测试来查找搜索到的ID是否与我的数据库条目相对应,我应该如何设置我想要定义的moqContext
对象?在示例中,我看到他们通常有自己的模拟对象的方法,但没有,所以我发现这个Mocking DbContext for TDD Repository让我尝试了这个测试。
感谢您的帮助!
答案 0 :(得分:1)
以下是使用内存数据库的示例。
首先,您创建一个模拟工作单元实例的请求。
Select count(distinct a.seller), sum(b.value)
from tab_sellers a
left join tab_sales b
on a.id_seller = b.seller
Select count(distinct seller), sum(value)
from tab_sales
然后你建立了模拟工作单元。根据我所读到的,需要单独的上下文(一个用于播种,一个用于测试)。 MockEntityFactory只返回一个虚拟数据数组,用于填充InMemoryDatabase中的dbsets。
[TestMethod]
public async Task ExampleTest() {
//arrange
Mock<IUnitOfWork> mockUow = MockUowFactory.Get(nameof(ExampleTest));
//act
using (var app = YOURAPP(mockUow.Object)){
app.METHODUNDERTEST();
}
//assert
...
}
然后我将这个工作单元通过必要的层,并且不需要做任何特殊的测试我的生产代码。