【问题标题】:FakeItEasy does not return expected valueFakeItEasy 不返回预期值
【发布时间】:2019-11-04 21:39:16
【问题描述】:

我正在尝试测试一种将字典作为参数的方法,通过删除一些不必要的条目来过滤它并返回结果字典。我已经单独编写了过滤类正常工作的测试,所以这个测试只关心过滤器被调用并返回字典。

由于某种原因,过滤器返回空字典,即使我用 FakeItEasy 明确告诉它要返回什么。 _callToChartOfAccountsFilterer 断言失败并显示以下消息:

以下调用的断言失败: TinyBooks.Services.Json.ChartOfAccounts.IChartOfAccountsFilterer.FilterAccounts(字典:忽略,过滤参数:忽略) 预计会准确找到一次,但在调用中没有找到: 1:TinyBooks.Services.Json.ChartOfAccounts.IChartOfAccountsFilterer.FilterAccounts(字典:[[Group1,System.Collections.Generic.List`1[TinyBooks.DomainModel.Dtos.AccountForParserDto]]],过滤参数:TinyBooks.Services.Json.ChartOfAccounts .ChartOfAccountsFilteringParameters)

ChartOfAccountsParser

public class ChartOfAccountsParser : IChartOfAccountsParser
{
    private readonly IJsonDeserializer _jsonDeserializer;
    private readonly IChartOfAccountsFilterer _chartOfAccountsFilterer;

    public ChartOfAccountsParser(IJsonDeserializer jsonDeserializer, IChartOfAccountsFilterer chartOfAccountsFilterer)
    {
        _jsonDeserializer = jsonDeserializer;
        _chartOfAccountsFilterer = chartOfAccountsFilterer;
    }

    public Dictionary<string, List<AccountForParserDto>> GetChartOfAccountsDictionaryBasedOnJsonFile(
        ChartOfAccountsParsingParameters parsingParameters)
    {
        var filePath = GetPathOfJsonFile(parsingParameters.FileName);
        var dictionary = ParseJsonToDictionary(filePath);
        var dic = _chartOfAccountsFilterer.FilterAccounts(dictionary, (ChartOfAccountsFilteringParameters)parsingParameters);
        return dic;
    }

    private string GetPathOfJsonFile(string fileName) => Path.Combine(GetFolderOfExecutingAssembly(), "ChartOfAccounts\\Json", fileName);

    private string GetFolderOfExecutingAssembly()
        => new Uri(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? throw new InvalidOperationException()).LocalPath;

    private Dictionary<string, List<AccountForParserDto>> ParseJsonToDictionary(string filePath) 
        => _jsonDeserializer.Load<Dictionary<string, List<AccountForParserDto>>>(filePath);
}

ChartOfAccountsParserTests

 [TestFixture]
public class ChartOfAccountsParserTests
{
    private IJsonDeserializer _jsonDeserializer;
    private IChartOfAccountsFilterer _chartOfAccountsFilterer;
    private AccountForParserDto _dto;
    private ChartOfAccountsParsingParameters _parameters;
    private string _key;
    private List<AccountForParserDto> _group;
    private Dictionary<string, List<AccountForParserDto>> _dictionary;
    private IReturnValueArgumentValidationConfiguration<Dictionary<string, List<AccountForParserDto>>> _callToJsonDeserializer;
    private IReturnValueArgumentValidationConfiguration<Dictionary<string, List<AccountForParserDto>>> _callToChartOfAccountsFilterer;

    [SetUp]
    public void Setup()
    {
        _jsonDeserializer = A.Fake<IJsonDeserializer>();
        _chartOfAccountsFilterer = A.Fake<IChartOfAccountsFilterer>();

        _dto = new AccountForParserDto { Name = "Account1" };
        _parameters = new ChartOfAccountsParsingParameters { FileName = "a.json" };
        _key = "Group1";
        _group = new List<AccountForParserDto> { _dto };
        _dictionary = new Dictionary<string, List<AccountForParserDto>> { [_key] = _group} ;

        _callToJsonDeserializer = A.CallTo(() => _jsonDeserializer.Load<Dictionary<string, List<AccountForParserDto>>>(A<string>._));
        _callToChartOfAccountsFilterer = A.CallTo(() => _chartOfAccountsFilterer.FilterAccounts(
            A<Dictionary<string, List<AccountForParserDto>>>._,
            A<ChartOfAccountsParsingParameters>._));

        _callToJsonDeserializer.Returns(_dictionary);
        _callToChartOfAccountsFilterer.Returns(_dictionary);
    }

    [Test]
    public void GetChartOfAccountsDictionaryBasedOnJsonFile_GivenDictionaryIgnoringParameters_ReturnsSameDictionary()
    {
        var parser = new ChartOfAccountsParser(_jsonDeserializer, _chartOfAccountsFilterer);

        var result = parser.GetChartOfAccountsDictionaryBasedOnJsonFile(_parameters);

        Assert.That(result.ContainsKey(_key));
        Assert.That(result.ContainsValue(_group));
        _callToJsonDeserializer.MustHaveHappenedOnceExactly();
        _callToChartOfAccountsFilterer.MustHaveHappenedOnceExactly();
    }
}

【问题讨论】:

  • 您的代码无法编译。即使抛开一些缺失的类,ChartOfAccountsParser.GetChartOfAccountsDictionaryBasedOnJsonFile 在声明之前就使用了变量dictionary。我不知道实际的方法是做什么的,所以很难说你出了什么问题。
  • 但是,当我用var dictionary = _chartOfAccountsFilterer.FilterAccounts(new Dictionary&lt;string, List&lt;AccountForParserDto&gt;&gt;()); 替换调用时,测试通过了。
  • @BlairConrad 为了清楚起见,我删除了一些代码,但我走得太远了。我将恢复编辑

标签: c# unit-testing nunit fakeiteasy


【解决方案1】:

我终于明白了。

问题出在此调用中被忽略参数的类型:

_callToChartOfAccountsFilterer = A.CallTo(() => _chartOfAccountsFilterer.FilterAccounts(
            A<Dictionary<string, List<AccountForParserDto>>>._,
            A<ChartOfAccountsParsingParameters>._));

我没有显示(很遗憾)是调用的方法的签名:

public interface IChartOfAccountsFilterer
{
    Dictionary<string, List<AccountForParserDto>> FilterAccounts(
        Dictionary<string, List<AccountForParserDto>> dictionary,
        IChartOfAccountsFilteringParameters filteringParameters);
}

当我将A&lt;ChartOfAccountsParsingParameters&gt;._ 更改为A&lt;IChartOfAccountsFilteringParameters&gt;._ 时,测试通过了。

【讨论】:

    【解决方案2】:

    使用以下支持成员作为基于您的示例的概念证明。

    public class Parser {
        private readonly IFilter filter;
        private readonly IProvider provider;
    
        public Parser(IFilter filter, IProvider provider) {
            this.filter = filter;
            this.provider = provider;
        }
    
        public Dictionary<string, List<Dto>> GetData() {
            Dictionary<string, List<Dto>> input = provider.Load();
            var dictionary = filter.Filter(input);
            return dictionary;
        }
    }
    
    public interface IProvider {
        Dictionary<string, List<Dto>> Load();
    }
    
    public interface IFilter {
        Dictionary<string, List<Dto>> Filter(Dictionary<string, List<Dto>> input);
    }
    
    public class Dto {
        public string Name { get; set; }
    }
    

    以下测试按预期运行

    [TestClass]
    public class DictionaryTests {
        [TestMethod]
        public void Sohuld_Return_Expected_Data() {
            //Arrange
            var key = "Group1";
            var dto = new Dto { Name = "Account1" };
            var group = new List<Dto> { dto };
            var dictionary = new Dictionary<string, List<Dto>> {
                { key, group }
            };
    
            var provider = A.Fake<IProvider>();
            A.CallTo(() => provider.Load()).Returns(dictionary);
    
            var filter = A.Fake<IFilter>();
            A.CallTo(() => filter.Filter(A<Dictionary<string, List<Dto>>>._))
                .Returns(dictionary);
    
            var subjectUnderTest = new Parser(filter, provider);
    
            //Act
            var actual = subjectUnderTest.GetData();
    
            //Assert - using FluentAssertions
            actual.ContainsKey(key).Should().BeTrue();
            actual.ContainsValue(group).Should().BeTrue();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-22
      • 2012-02-04
      • 2012-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多