2016-03-09 54 views
1

我正在用Moq创建我的第一个测试单元,但似乎无法使其工作。用Moq和一个通用仓库进行单元测试

我有一个注入我的ApplicationDbContext的通用资源库。我试图收到一份存储在数据库中的所有食物的清单。在我真正的服务中,我使用简单注射器,一切正常。

ApplicationDbContext:

public class ApplicationDbContext : IdentityDbContext<AppUser> 
{ 
    public ApplicationDbContext() 
     : base("ApplicationDbContext") 
    { 
    } 
    ... 
} 

通用存储库:

public class Repository<T> : IRepository<T> where T : class 
{ 
    private ApplicationDbContext _context; 
    private readonly IDbSet<T> _entities; 

    public Repository(ApplicationDbContext context) 
    { 
     _context = context; 
     _entities = _context.Set<T>(); 
    } 

    .. async methods .. (GetAllAsync) 
} 

Moq的测试:

[TestClass] 
public class FoodServicesTest 
{ 
    private Mock<IRepository<Food>> _foodRepository; 

    [TestInitialize] 
    public void Initialize() 
    { 
     _foodRepository = new Mock<IRepository<Food>>(); 
    } 

    [TestMethod] 
    public async Task CanGetAllFoods() 
    { 
     // Before edit 2 
     //IList<Food> foods = await _foodRepository.Object.GetAllAsync(); 
     //_foodRepository.Setup(m => m.GetAllAsync()).ReturnsAsync(foods); 

     _foodRepository.Setup(m => m.GetAllAsync()).ReturnsAsync(List<Food>()); 
     IList<Food> foods = await _foodRepository.Object.GetAllAsync(); 

     Assert.IsTrue(foods.Count >= 1); 
    } 
} 

编辑2:

将上面的安装程序放在GetAllAsync()(谢谢Patrick Quirk)并将其参数替换为'new List()'之后,食物列表不再返回null,但计数0大概是更好的,但我期望它是2(如服务中)。

+0

不能告诉res'是什么',而是移动调用'GetAllAsync'你上面的'Setup'电话。 –

+0

好的,谢谢,那个小小的调整之后,食物清单并不是空的,而是有一个计数0(请参阅编辑2) – Svlet

回答

0

返回值是一个空列表。这是由下面这行代码

_foodRepository.Setup(m => m.GetAllAsync()).ReturnsAsync(new List<Food>()); 

上面的指令,实际上是告诉模拟对象调用GetAllAsync时返回一个新的空单的规定。

而是应该建立新的食品对象从数据库中以“模拟”的结果,像这样:

var foodList = new List<Food>(); 
foodList.Add(new Food() { ...insert your mocked values here }); 
foodList.Add(new Food() { ...insert your mocked values here }); 
_foodRepository.Setup(m => m.GetAllAsync()).ReturnsAsync(foodList); 

编辑

看代码更好,我只能看到你”重新使用模拟对象,看看是否返回结果。你确定这真的需要这个测试吗?在涉及某些业务逻辑进行测试时,在存储库上使用模拟对象很有用。也许你的代码只是为了提出问题而重写,但值得指出。

+0

哦谢谢,我明白了。我假设创建和填充新列表仅仅是一些教程用来避免获取数据库数据的例子。我会试一试。 – Svlet

+0

好吧,它的工作。并回答你的编辑:测试会变得更复杂,目前我只是想知道Moq框架是如何工作的。谢谢! – Svlet

+0

快乐黑客:) –

0

您可以指定要返回的值是这样的:

var foods=new List<Food>(); 
//// add two items here 
foods.Add(new food(){.. set values }); 
foods.Add(new food(){.. set values }); 

_foodRepository.Setup(m => m.GetAllAsync()).ReturnsAsync(foods); 
IList<Food> foods = await _foodRepository.Object.GetAllAsync();