使用最小起订量和通用存储库进行单元测试

Unit testing with Moq and a Generic Repository

我正在用最小起订量创建我的第一个测试单元,但似乎无法正常工作。

我有一个注入我的 ApplicationDbContext 的通用存储库。我正在尝试接收存储在数据库中的所有食物的列表。在我的实际服务中,我使用 Simple Injector,一切正常。

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)
}

起订量测试:

[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()' 之后,食物列表不再 return 为 null,而是计数 0,大概是更好,但我希望它是 2(就像在服役中一样)。

return 值为空列表。这是由您的这行代码指定的

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

上面的指令实际上是在调用 GetAllAsync 时告诉模拟对象 return 一个新的空列表。

您应该改为创建新的 Food 对象 "simulate" 来自数据库的结果,如下所示:

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);

编辑

仔细查看代码,我只能看到您只是在使用模拟对象并查看 return 是否有结果。你确定真的需要这个测试吗?当需要测试一些业务逻辑时,在存储库上使用模拟对象很有用。也许您的代码只是为了提出问题而被重写,但值得指出这一点。

您可以这样指定 return 的值:

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();