.Net Core C# 如何获取具有私有成员字段的对象并设置这些私有对象的方法?

问题描述 投票:0回答:1

我正在使用.Net Core 8,并且我有以下课程:

public class UserRepository : EfRepository<User>, IUserRepository
{
    private readonly IJwtFactory _jwtFactory;
    private readonly IJwtTokenValidator _jwtTokenValidator;
    private readonly ITokenFactory _tokenFactory;
    private readonly UserManager<AppUser> _userManager;
    private readonly SignInManager<AppUser> _signInManager;
    private readonly IMapper _mapper;
    private readonly ILogger<UserRepository> _logger;
    public UserRepository(ILogger<UserRepository> logger, UserManager<AppUser> userManager, SignInManager<AppUser> signInManager, IMapper mapper, AppDbContext appDbContext, IJwtFactory jwtFactory, IJwtTokenValidator jwtTokenValidator, ITokenFactory tokenFactory) : base(appDbContext)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _jwtFactory = jwtFactory;
        _jwtTokenValidator = jwtTokenValidator;
        _tokenFactory = tokenFactory;
        _mapper = mapper;
        _logger = logger;
    }
public async virtual Task<MyResponse> MethodUnderTest(string id)
{
_userManager.DoSomeThing(); // Moq'ed object
_signInManager.DoSomeThins(); // Moq'ed object
}
<snip>
}

(1) 我应该

Moq
IUserRepository
还是物体?如何设置私有对象
UserManager
SignInManager
的函数调用?事实上,我如何将
Moq
UserManager
中的
SignInManager
传递给
Moq
ed
IUserInterface

(2) 当我

Moq
UserRepository
对象时,将
Moq
对象传递给测试构造函数下的另一个对象时遇到以下异常:

System.ArgumentException : Can not instantiate proxy of class: Web.Api.Infrastructure.Data.Repositories.UserRepository.
Could not find a constructor that would match given arguments:
Castle.Proxies.ILogger`1Proxy
Castle.Proxies.UserManager`1Proxy
Castle.Proxies.SignInManager`1Proxy
Castle.Proxies.IMapperProxy
Castle.Proxies.AppDbContextProxy
Castle.Proxies.IJwtFactoryProxy
Castle.Proxies.IJwtTokenValidatorProxy
Castle.Proxies.ITokenFactoryProxy
 (Parameter 'constructorArguments')
---- System.MissingMethodException : Constructor on type 'Castle.Proxies.UserRepositoryProxy' not found.

目标是能够最小化测试中涉及

UserRepository
方法的所有对象,并使用相应的方法
Setup
进行测试。为此,我有一个类固定装置,它创建所有
moq

public class InfrastructureTestBase : IDisposable
{
    public Mock<UserManager<AppUser>> UserManager { get; } = new Mock<UserManager<AppUser>>(Mock.Of<IUserStore<AppUser>>(), null, null, null, null, null, null, null, null);
    public Mock<SignInManager<AppUser>> SignInManager { get; }
    public Mock<ILogger<IUserRepository>> Logger { get; } = new Mock<ILogger<IUserRepository>>();
    public Mock<IMapper> Mapper { get; } = new Mock<IMapper>();
    public Mock<AppDbContext> AppDbContext { get; } = new Mock<AppDbContext>(new DbContextOptions<AppDbContext>());
    public Mock<IJwtFactory> JwtFactory { get; } = new Mock<IJwtFactory>();
    public Mock<IJwtTokenValidator> JwtTokenValidator { get; } = new Mock<IJwtTokenValidator>();
    public Mock<UserRepository> UserRepository { get; private set; }
    public Mock<ITokenFactory> TokenFactory { get; } = new Mock<ITokenFactory>();
    public InfrastructureTestBase()
    {
        SignInManager = new Mock<SignInManager<AppUser>>(UserManager.Object, Mock.Of<IHttpContextAccessor>(), Mock.Of<IUserClaimsPrincipalFactory<AppUser>>(), null, null, null, null);
        SignInManager.Setup(i => i.RefreshSignInAsync(It.IsAny<AppUser>()));
        UserRepository = new Mock<UserRepository>(Logger.Object, UserManager.Object, SignInManager.Object, Mapper.Object, AppDbContext.Object, JwtFactory.Object, JwtTokenValidator.Object, TokenFactory.Object);
    }

    public void Dispose()
    {
        //throw new NotImplementedException();
    }
}
c# .net-core asp.net-identity moq asp.net-core-8
1个回答
0
投票

如果您需要编写

UserRepository
类本身的测试,那么您可以创建其所有依赖项的 Test Doubles,如 OP 中所示。

无需创建

Mock<UserRepository>
,因为在这种情况下,
UserRepository
对象是被测系统 (SUT):

var userRepository = new UserRepository(
    Logger.Object,
    UserManager.Object,
    SignInManager.Object,
    Mapper.Object,
    AppDbContext.Object,
    JwtFactory.Object,
    JwtTokenValidator.Object,
    TokenFactory.Object);
// Test code that exercises userRepository go here; e.g.
var actual = await userRepository.MethodUnderTest("foo");

另一方面,如果您需要测试另一个依赖于

IUserRepository
的类,只需创建它的测试替身:

var userRepositoryTD = new Mock<IUserRepository>();
// Configure one or more interface members if needed:
userRepositoryTD.Setup(r => r.MethodUnderTest("foo")).ReturnsAsync(whatever);
// Now pass the Test Double to your actual SUT
var sut = new MyClass(userRepositoryTD.Object);
// Then add test code that exercises the sut here...

userRepositoryTD.Object
IUserRepository
接口的动态生成实现,它与具体的
UserRepository
类没有任何关系。因此,在这种情况下,无需配置任何
UserRepository
类的依赖项(
userManager
userManager
等)。
userRepositoryTD.Object
没有这些依赖性。

© www.soinside.com 2019 - 2024. All rights reserved.