Проверка вызовов на несколько возвращенных, завернутых подделок с помощью FakeItEasy - PullRequest
0 голосов
/ 09 октября 2018

У меня есть два таких интерфейса:

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

Можетэто будет сделано?

РЕДАКТИРОВАТЬ:

Я должен уточнить, что на самом деле будет несколько сотен транзакций и несколько вызовов Write для каждой.И реализации Store и Tx сложны.Это для интеграционного теста, и я использую FakeItEasy для проверки поведения пакетирования при различных настройках.Хотя это может быть слишком далеко от предполагаемого варианта использования библиотеки:)

Я предполагаю, что я спрашиваю, могу ли я собирать и предпочтительно объединять поддельные транзакции, не делая это вручную.Я могу представить что-то вроде ReturnLazily с побочным эффектом сбора возвращаемых подделок, но это довольно неуправляемо и трудно читаемо (и я не мог заставить работать часть утверждения).

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

С обновленными требованиями я попробовал такую ​​вещь, и она прошла.Я уверен, что это все еще слишком упрощенно, но похоже, что ваши тесты будут разнообразными и странными, и у меня действительно нет шансов написать что-то, что будет соответствовать вашему конкретному варианту использования.Однако, введя небольшой фабричный класс, я достиг некоторого уровня читабельности (на мой взгляд) и смог собрать созданные транзакции:

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 не совсем подходит для использования, так что вы, вероятно, в конечном итоге будете выполнять много пользовательского кодирования в библиотеке.

0 голосов
/ 09 октября 2018

Предполагая, что вы хотите написать 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();
}

Но если вы действительно хотите убедиться, что два вызова были сделаны без проверки того, что каждая транзакция была ответственна за 1 запись, вы можете

[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();
}

По моему мнению, намного проще понять, что происходит.Но, возможно, вы просто упростили ради того, чтобы задать вопрос.

...