У меня есть несколько методов бизнес-логики, которые хранят и извлекают (с фильтрацией) объекты и списки объектов из кэша.
Рассмотреть возможность
IList<TObject> AllFromCache() { ... }
TObject FetchById(guid id) { ... }
IList<TObject> FilterByPropertry(int property) { ... }
Fetch..
и Filter..
вызвал бы, AllFromCache
который заполнил бы кэш и возвратился бы, если это не там, и просто возвратился бы от этого, если это есть.
Я вообще избегаю модульного тестирования этих. Каковы лучшие практики для модульного тестирования против такого типа структуры?
Я рассмотрел заполнение кэша в TestInitialize и удаление в TestCleanup, но мне это не кажется правильным (хотя это вполне может быть).
источник
Принцип единой ответственности - ваш лучший друг здесь.
Прежде всего, переместите AllFromCache () в класс репозитория и назовите его GetAll (). То, что он извлекает из кэша, является подробностью реализации хранилища и не должно быть известно вызывающему коду.
Это делает тестирование вашего класса фильтрации приятным и легким. Больше не волнует, откуда ты это взял.
Во-вторых, оберните класс, который получает данные из базы данных (или где-либо еще) в оболочку кэширования.
АОП является хорошей техникой для этого. Это одна из немногих вещей, в которых она очень хороша.
Используя такие инструменты, как PostSharp , вы можете настроить его так, чтобы любой метод, отмеченный выбранным атрибутом, был кэширован. Однако, если это единственное, что вы кэшируете, вам не нужно заходить так далеко, чтобы иметь AOP-фреймворк. Просто имейте Repository и Caching Wrapper, которые используют один и тот же интерфейс, и вставьте его в вызывающий класс.
например.
Посмотрите, как вы удалили знания о реализации репозитория из ProductManager? Посмотрите также, как вы придерживались принципа единой ответственности, имея класс, который обрабатывает извлечение данных, класс, который обрабатывает извлечение данных, и класс, который обрабатывает кэширование?
Теперь вы можете создать экземпляр ProductManager с любым из этих репозиториев и получить кеширование ... или нет. Это невероятно полезно позже, когда вы получаете запутанную ошибку, которая, как вы подозреваете, является результатом кэша.
(Если вы используете контейнер IOC, даже лучше. Должно быть очевидно, как адаптироваться.)
И в ваших тестах ProductManager
Не нужно тестировать кеш вообще.
Теперь возникает вопрос: я должен проверить этот CachedProductRepository? Я предлагаю нет. Кеш довольно неопределенный. Фреймворк делает с ним вещи, которые находятся вне вашего контроля. Например, просто убрать из него вещи, когда они переполнятся, например. Вы закончите тестами, которые не пройдут однажды в голубой луне, и вы никогда не поймете почему.
И, внеся изменения, которые я предложил выше, на самом деле не так уж много логики для тестирования. Там будет действительно важный тест, метод фильтрации, который будет полностью абстрагирован от деталей GetAll (). GetAll () просто ... получает все. Откуда-то
источник
Ваш предложенный подход - то, что я сделал бы. Учитывая ваше описание, результат метода должен быть одинаковым независимо от того, присутствует объект в кэше или нет: вы все равно должны получить тот же результат. Это легко проверить, настроив кеш определенным образом перед каждым тестом. Возможно, есть несколько дополнительных случаев, например, если guid имеет
null
или не имеет объекта, у которого есть запрошенное свойство; те могут быть проверены тоже.Кроме того, вы можете считать ожидаемым, что объект будет присутствовать в кеше после возврата вашего метода, независимо от того, был ли он в кеше вообще. Это спорно, так как некоторые люди (включая меня) , утверждают , что вы заботитесь о том, что вы получите обратно из своего интерфейса, а не как вы получите его (то есть ваше тестирование , что интерфейс работает , как и ожидалось, не то, что он имеет конкретной реализации). Если вы считаете это важным, у вас есть возможность проверить это.
источник
На самом деле, это единственный правильный способ сделать. Вот для чего нужны эти две функции: установить предварительные условия и выполнить очистку. Если предварительные условия не выполнены, ваша программа может не работать.
источник
Я работал над некоторыми тестами, которые недавно использовали кеширование. Я создал оболочку для класса, которая работает с кешем, а затем получил утверждения, что эта оболочка вызывается.
Я сделал это главным образом потому, что существующий класс, который работает с кешем, был статическим.
источник
Похоже, вы хотите проверить логику кэширования, но не логику заполнения. Поэтому я бы посоветовал вам высмеивать то, что вам не нужно тестировать - заполнять.
Ваш
AllFromCache()
метод заботится о заполнении кэша, и это должно быть делегировано другому, например, поставщику ценностей. Так ваш код будет выглядетьТеперь вы можете издеваться над поставщиком для теста, чтобы вернуть некоторые предопределенные значения. Таким образом, вы можете проверить фактическую фильтрацию и выборку, а не загружать объекты.
источник