在ASP.NET C#中使用xUnit和Moq模拟依赖库

eivnm1vs  于 2023-01-18  发布在  .NET
关注(0)|答案(1)|浏览(123)

我尝试使用xUnit和Moq来测试我的存储库,但是在设置模拟存储库时遇到了麻烦。
这是我的考验:

[Theory]
[InlineData(1, null)]
public async Task GetLevelsAsync_ReturnsArgumentNullException(int appId, string year)
{
    //Arrange
    IOptions<Settings> options = Options.Create(set);
    Mock<ILoggerFactory> _loggerFactory = new Mock<ILoggerFactory>();
    Mock<ILogger<GeoRepository>> _loggerGeoRepository = new Mock<ILogger<GeoRepository>>();
    Mock<DataProviderFactory> _dataProviderFactory = new Mock<DataProviderFactory>(_loggerFactory, options);
    GeoRepository geo = new GeoRepository (_loggerGeoRepository.Object, options, _dataProviderFactory.Object);

    //Act
    Func<Task> action = async () => await geo.GetLevelsByYear(appId, year);

    //Assert
    var ex = await Assert.ThrowsAsync<ArgumentNullException>(action);
    Assert.Contains("Value cannot be null", ex.Message);
}

这是我的仓库

public class GeoRepository : BaseRepository, IGeoRepository
{
    public GeoRepository(ILogger<GeoRepository> logger, 
        IOptions<Settings> settings,
        DataProviderFactory dpFactory) : base(logger, settings, dpFactory)
    {
    }

    public async Task<List<Year>> GetLevelsByYear(int appId, string year)
    {

        if (string.IsNullOrWhiteSpace(year))
            throw new ArgumentNullException(nameof(year));

        var result = new List<Level>();

        var parameters = new { AppId = appId, Year = year};

        string sql = @"SELECT * FROM [Table] WHERE AppId = @AppId AND DataYear = @Year";

        using (IDbConnection db = new SqlConnection(_settings.SqlServerConnString))
        {
            try
            {
                result = db.Query<Level>(sql, parameters).ToList();
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Error querying levels by year", new { appId, year});
                throw;
            }
        }
        return result;
    }
}

当我运行测试时,我收到以下错误消息:

System.ArgumentException : Can not instantiate proxy of class: Project.Services.Data.API.Infrastructure.DataProviderFactory.
Could not find a constructor that would match given arguments:
Moq.Mock`1[Microsoft.Extensions.Logging.ILoggerFactory]
Microsoft.Extensions.Options.OptionsWrapper`1[Project.Services.Data.API.Settings]
(Parameter 'constructorArguments')
---- System.MissingMethodException : Constructor on type 'Castle.Proxies.DataProviderFactoryProxy' not found.

这是我的DataProviderFactory,我在模拟时遇到问题,请参见上面的错误消息:

public class DataProviderFactory
{
    private ILoggerFactory _loggerFactory;
    private IOptions<Settings> _settings;
    public DataProviderFactory(ILoggerFactory loggerFactory, IOptions<Settings> settings)
    {
        _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
        _settings = settings?? throw new ArgumentNullException(nameof(settings));

    }
    public DataProvider GetProvider(DatabaseProvider provider)
    {
        switch (provider)
        {
            case DatabaseProvider.SqlServer:
                {
                    var logger = _loggerFactory.CreateLogger<SqlProvider>();
                    return new SqlProvider(logger, _settings);
                }
            case DatabaseProvider.Snowflake:
                {
                    var logger = _loggerFactory.CreateLogger<SnowFlakeProvider>();
                    return new SnowFlakeProvider(logger, _settings);
                }
            default:
                {
                    var logger = _loggerFactory.CreateLogger<SqlProvider>();
                    return new SqlProvider(logger, _settings);
                }
        }
    }
}
qojgxg4l

qojgxg4l1#

它不起作用,因为错误消息在Year情况下返回null参数。值不能为null。(参数'year')。
以正确的方式验证错误将是这样的...

//Assert
        await Assert.ThrowsAsync<ArgumentNullException>(action);

并且这本身不需要验证异常消息,因为Assert本身通过验证错误类型来播放异常消息
是的,这意味着如果您在运行时打开任何其他异常,它将不会被视为有效测试
希望这能帮上忙

相关问题