Модульное тестирование, это хорошая идея, чтобы убедиться, что методы не называются - PullRequest
0 голосов
/ 16 октября 2018

Допустим, у вас есть следующий метод для тестирования:

public void foo(object myObject, bool myBool)
{
     if(myBool)
        repositoryA.save(myObject)
     else
        repositoryB.save(myObject)
}

Каков наилучший способ для модульного тестирования такой функции?Если вы напишите 2 теста, в которых assert repositoryA вызывается, когда myBool имеет значение true, и repositoryB вызывается, когда myBool имеет значение false, то следующее изменение функции все равно выполнит тесты успешно, но потенциально нарушит функциональность приложения:

public void foo(object myObject, bool myBool)
{
    repositoryA.save(myObject)
    repositoryB.save(myObject)
}

С другой стороны, если вы утверждаете, что когда myBool имеет значение true, то хранилище A называется И что хранилище B не вызывается, что дает вам больше уверенности в том, что любое изменение в функции не приведет к ошибкам, но тогда у вас естьтест, который зависит от деталей реализации.Какой лучший способ сделать это?

А что, если вы используете TDD, какие тесты вы бы написали, чтобы достичь желаемой функциональности?

Ответы [ 2 ]

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

Каков наилучший способ модульного тестирования такой функции?

Начать с его редизайна?

Частью разработки тестов в первую очередь является утверждение, что тестируемые интерфейсы также «лучше»;более легко потребляемый, более легко обслуживаемыйодин вам нужен для вашего варианта использования.

Две возможности:

Во-первых, код пытается вам сказать, что у вас есть требования к телеметрии;чтобы у вас была возможность запрашивать тестируемую систему и узнать, сколько объектов было сохранено в каждом хранилище, или каким был последний объект, сохраненный в каждом хранилище, или что-то в этом духе.

Тогда вы можете использоватьтелеметрия для написания вашего теста

Given:
    telemetry reports that repository B has stored 7 objects
    and myBool is true
When:
    foo()
Then:
    telemetry reports that repository B has stored 7 objects

Это в основном разбивает проблему на две части;набор тестов, которые гарантируют, что телеметрия точно сообщает количество раз, когда хранилище сохранило объект, а затем тест foo(), который предполагает, что телеметрия работает.

Второй вариант: тест пытаетсясказать вам, что вы хотите, чтобы иметь возможность оценить, какие побочные эффекты происходят в программе.Так что сделайте эти эффекты первоклассным гражданином в вашем дизайне и напишите тесты, которые проверят эффекты.

List<Effect> foo () {
    if (myBool) {
        return List.of(SaveInRepositoryA);
    } else {
        return List.of(SaveInRepositoryB);
    }
}

Теперь ваше утверждение стало проще - вы просто убедитесь, что в списке есть нужное количество элементов,и правильные элементы.

Важное замечание: эти проекты создают шов между вашей логикой и побочными эффектами.Представьте себе границу, на одной стороне которой находится сложная логика, которую легко проверить, потому что это все манипуляции с данными в памяти;на другой стороне границы находится код, который сложно проверить, но он настолько прост и понятен, что в нем явно нет ошибок.

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

Придерживаясь вашего вопроса (пожалуйста, прочитайте также мой комментарий, может быть более ценным в более общем смысле), я написал бы что-то вроде этого: (используя JMock, библиотеку Java Mocking)

// with myBool == true

context.checking(new Expectations(){{
    oneOf(repositoryA).save(object);
    never(repositoryB);
}});

underTest.foo(object, true);




// with myBool == false

context.checking(new Expectations(){{
    never(repositoryA);
    oneOf(repositoryB).save(object);
}});

underTest.foo(object, false);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...