代码之家  ›  专栏  ›  技术社区  ›  asgerhallas

检查多个返回的电话,包装假货与假货

  •  1
  • asgerhallas  · 技术社区  · 6 年前

    我有两个这样的接口:

    public interface Store { Tx BeginTx() }
    public interface Tx { void Write() }
    

    我有这样一个方法:

    void WriteALot(fakeStore) 
    {
        var tx1 = fakeStore.BeginTx();
        tx1.Write();
    
        var tx2 = fakeStore.BeginTx();
        tx2.Write();
    }
    

    还有一个测试:

    var fakeStore = A.Fake<Store>(x => x.Wrapping(realstore));
    
    // A.CallTo(() => fakeStore.BeginTx()).ReturnAWrappedTx()?
    
    WriteALot(fakeStore);
    
    // Check that a total of two calls were made to the Tx's
    

    编辑:

    我要澄清的是,实际上会有几百个事务和多个写调用。而且Store和Tx的实现非常复杂。这是一个集成测试,我使用FakeItEasy检查不同设置下的批处理行为。不过,它可能离库的预期用例有点太远:)

    我想我要问的是,我是否可以收集并最好合并伪造的交易,而不必手动操作。我可以想象像returnlazy这样的东西会带来收集返回的假货的副作用,但这是相当难以管理和难以阅读的(我无法让断言部分工作)。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Blair Conrad    6 年前

    随着需求的更新,我尝试了这种方法,结果通过了。我相信这仍然过于简单化,但听起来你的测试会变得多样和怪异,我真的没有机会写出适合你特定用例的东西。但是,通过引入一个小型工厂类,我获得了一定程度的可读性(在我看来),并且能够收集创建的事务:

    private class TransactionFactory
    {
        private readonly IList<Tx> allTransactions = new List<Tx>();
    
        public IEnumerable<Tx> AllTransactions => allTransactions;
    
        public Tx Create()
        {
            var realTransaction = new RealTransaction();
            var fakeTransaction = A.Fake<Tx>(options =>
                        options.Wrapping(realTransaction));
            allTransactions.Add(fakeTransaction);
            return fakeTransaction;
        }
    }
    
    
    [Test]
    public void UpdatedTests()
    {
        var realStore = new RealStore();
        var fakeStore = A.Fake<Store>(x => x.Wrapping(realStore));
    
        var transactionFactory = new TransactionFactory();
    
        A.CallTo(() => fakeStore.BeginTx()).ReturnsLazily(transactionFactory.Create);
    
        WriteALot(fakeStore);
    
        Assert.That(transactionFactory.AllTransactions.SelectMany(Fake.GetCalls).Count(),
                    Is.EqualTo(2));
    }
    

    这应该可以进行各种修改,但正如您所指出的,FakeItEasy的使用并不完全符合预期,因此您很可能会在库中进行大量自定义编码。

        2
  •  1
  •   Blair Conrad    6 年前

    tx1.Write tx2.Write 在上面,您可以轻松地检查每个事务是否被调用一次,这可能比检查总共调用了两次更有用:

    public void Test()
    {
        var realStore = new RealStore();
        var fakeStore = A.Fake<Store>(x => x.Wrapping(realStore));
    
        var realTransaction1 = new RealTransaction();
        var realTransaction2 = new RealTransaction();
    
        var wrappedTransaction1 = A.Fake<Tx>(options => options.Wrapping(realTransaction1));
        var wrappedTransaction2 = A.Fake<Tx>(options => options.Wrapping(realTransaction2));
        A.CallTo(() => fakeStore.BeginTx())
            .Returns(wrappedTransaction1).Once().Then
            .Returns(wrappedTransaction2);
    
        WriteALot(fakeStore);
    
        A.CallTo(() => wrappedTransaction1.Write()).MustHaveHappenedOnceExactly();
        A.CallTo(() => wrappedTransaction2.Write()).MustHaveHappenedOnceExactly();
    }
    

    但是如果您真的想确保两个调用都是在不检查每个事务是否负责一次写入的情况下进行的,那么您可以

    [Test]
    public void LaxTest()
    {
        int numberOfTransactionCalls = 0;
    
        var realStore = new RealStore();
        var fakeStore = A.Fake<Store>(x => x.Wrapping(realStore));
    
        var realTransaction1 = new RealTransaction();
        var realTransaction2 = new RealTransaction();
    
        var wrappedTransaction1 = A.Fake<Tx>(options => options.Wrapping(realTransaction1));
        var wrappedTransaction2 = A.Fake<Tx>(options => options.Wrapping(realTransaction2));
    
        A.CallTo(() => wrappedTransaction1.Write()).Invokes(() => ++numberOfTransactionCalls);
        A.CallTo(() => wrappedTransaction2.Write()).Invokes(() => ++numberOfTransactionCalls);
    
        A.CallTo(() => fakeStore.BeginTx())
            .Returns(wrappedTransaction1).Once().Then
            .Returns(wrappedTransaction2);
    
        WriteALot(fakeStore);
    
        Assert.That(numberOfTransactionCalls, Is.EqualTo(2));
    }
    

    [Test]
    public void UnwrappedTest()
    {
        var fakeStore = A.Fake<Store>();
        var transaction1 = A.Fake<Tx>();
        var transaction2 = A.Fake<Tx>();
        A.CallTo(() => fakeStore.BeginTx())
            .Returns(transaction1).Once().Then
            .Returns(transaction2);
    
        WriteALot(fakeStore);
    
        A.CallTo(() => transaction1.Write()).MustHaveHappenedOnceExactly();
        A.CallTo(() => transaction2.Write()).MustHaveHappenedOnceExactly();
    }
    

    在我看来,理解发生了什么要容易得多。但也许你只是为了问问题而简化了。