asp.net 如何测试调用服务的API以及该服务调用存储库的API?

tjvv9vkg  于 2022-11-26  发布在  .NET
关注(0)|答案(1)|浏览(181)

我有四个项目需要测试(我的设计模式类似于https://exceptionnotfound.net/the-repository-service-pattern-with-dependency-injection-and-asp-net-core/)。第一个项目是数据访问层项目,从数据库中获取数据。第二个项目是存储库项目,通过数据访问层项目对数据库中的实体进行CRUD操作。这是一个仓库项目中的通用接口的例子,它是为数据库中的所有实体实现的,

public interface IEntityBaseRepository<T> where T : class, IEntityBase, new()
    {
        IEnumerable<T> AllIncluding(
          params Expression<Func<T, object>>[] includeProperties
        );
        IEnumerable<T> GetAll();
        int Count();
        T GetSingle(int id);
        T GetSingle(Expression<Func<T, bool>> predicate);
        T GetSingle(
          Expression<Func<T, bool>> predicate,
          params Expression<Func<T, object>>[] includeProperties
        );
        IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate);
        T Add(T entity);
        void Update(T entity);
        void Delete(T entity);
        void DeleteWhere(Expression<Func<T, bool>> predicate);
        void Commit();
    }

第三个项目是一个服务项目,它满足应用程序所需的逻辑,它处理存储库项目,并根据系统的需要创建对象和函数,下面是项目中一个服务的摘录,

public class EmployeeService : IEmployeeService
    {
        private IEntityBaseRepository<Employee> _employeeRepository;
        private IEntityBaseRepository<User> _userRepository;
        private IEntityBaseRepository<UserRole> _userRoleRepository;
        private IEntityBaseRepository<Role> _roleRepository;
        public EmployeeService(IEntityBaseRepository<Employee> employeeRepository, IEntityBaseRepository<User> userRepository, IEntityBaseRepository<UserRole> userRoleRepository, IEntityBaseRepository<Role> roleRepository)
        {
            _employeeRepository = employeeRepository;
            _userRepository = userRepository;
            _userRoleRepository = userRoleRepository;
            _roleRepository = roleRepository;
        }
        .
        .
        .
        public List<EmployeeServiceModel> GetAllEmployeesForUser(string username)
        {
            var user = _userRepository.GetAll().FirstOrDefault(u => u.UserName == username);
            var userRoles = _userRoleRepository.GetAll().Where(ur => ur.UserId == user.Id);
            var roles = _roleRepository.GetAll();
            var currentRoles = new List<Role>(); 
         
            if (userRoles != null && userRoles.Count() > 0)
            {
                currentRoles = roles.Where(r => userRoles.Any(ur => ur.RoleId == r.Id)).ToList();
            }
            else
            {
                throw new UnauthorizedAccessException(); 
            }
            . 
            . 
            .

从上面可以看出,它依赖于存储库项目。
最后,向世界公开服务的API项目

public class EmployeesController : ControllerBase
{
    private IEmployeeService _employeeService;

    public EmployeesController(IEmployeeService employeeService)
    {
        _employeeService = employeeService;
    }

    // GET: api/<EmployeesController>
    [HttpGet]
    public async Task<IActionResult> Get(string username)
    {
        var employees = _employeeService.GetAllEmployeesForUser(username); 
        return Ok(employees);
    }

问题是,如何对上面的解决方案进行单元测试?我应该只测试API吗?如果是,怎么做?项目依赖于服务接口,而服务接口又依赖于仓库。我不能只创建一个假的雇员列表,然后让服务中的“GetAllEmployeesForUser”函数返回它们。如果我想测试用户是否未经授权,或者没有员工?我应该只测试服务项目吗?而不需要测试API?

enyaitl3

enyaitl31#

如果您想测试整个Web API(集成测试),您可以在这里找到所有信息:https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-7.0
如果你想做单元测试,你可以用MoqSubstitute库模拟特定测试用例中不需要的部分,并在你想测试的部分执行。例如,如果你只想测试EmployeeService逻辑:

var employeesRepMock = new Mock<IEntityBaseRepository<Employee>>();
var usersRepMock =  new Mock<IEntityBaseRepository<User>>();
var userRolesRepMock = new Mock<IEntityBaseRepository<UserRole>>();
var rolesRepMock = new Mock<IEntityBaseRepository<Role>>();

rolesRepMock.Setup(m => m.GetAll().Returns(new List<Role> {
 // test roles here
}));
usersRepMock.Setup(m => m.GetAll().Returns(new List<User> {
 // test users here
}));
employeesRepMock.Setup(m => m.GetAll().Returns(new List<Employee> {
 // test employees here
}));
userRolesRepMock.Setup(m => m.GetAll().Returns(new List<UserRoles> {
 // test user roles here
}));

var service = new EmployeeService(employeesRepMock.Object, 
   usersRepMock.Object, userRolesRepMock.Object, rolesRepMock.Object);

var result = service.GetAllEmployeesForUser("test-username");

// your checks ..
Assert.Greater(result.Length, 0);

要测试EF Core逻辑,可以使用InMemory数据库。

相关问题