Spring: издевательский сервис повышенной безопасности

Мы реализуем часть нашей безопасности на уровне обслуживания, поэтому я добавляю аннотацию @PreAuthorize к некоторым методам MyService.

На MyServiceSecurityTest я хочу протестировать только матрицу безопасности-роль-разрешение, без какой-либо бизнес-логики. По этой причине мне приходится издеваться над MyService. проблема в том, что и Mockito, и Spring используют прокси-серверы CGLIB, а мой сервис не улучшен с помощью @PreAuthorize после Mockito.mock(MyService.class).

Есть ли способ имитировать сервис и сохранить логику @PreAuthorize?


Пример:

@Service
public class MyService implements IMyService {

    @Override
    @PreAuthorize("hasAuthority('SYSOP')")
    public void someMethod(ComplexDTO dto) {
        // lots of logic and dependencies, require lots of stubbing.
    }
}

Чтобы избежать инициализации всех зависимостей MyService#someMethod и сборки ComplexDTO на MyServiceSecurityTest, я хочу имитировать MyServiceSecurityTest, но сохранить проверки @PreAuthorize.

Другой простой способ - просто переопределить метод обслуживания, который вы не хотите тестировать.

cosmos 24.04.2018 16:44

@cosmos Я не знаком с @MockBean. Я только что заменил @Mock MyService service на @MockBean MyService service и получил тот же результат. Я что-то пропустил? Почему вы думаете, что это поможет?

VB_ 24.04.2018 16:45

@cosmos Мне не нужно ничего переопределять. Я хочу опробовать все методы

VB_ 24.04.2018 16:46

@cosmos мне нужно поиздеваться и протестировать @PreAuthorize("hasAuthority('SYSOP')") public void someMethod() { ... }

VB_ 24.04.2018 16:46

Почему бы вам не поставить под вопрос весь класс, который вы хотите протестировать, и удалить логику, которую вы не хотите показывать публике. Так вам будет легче понять вашу проблему.

cosmos 24.04.2018 16:48

@dur нет, насколько я понимаю, аннотация @PreAuthorize не будет работать на уровне интерфейса, и я должен объявить безопасность на уровне реализации и принудительно использовать проксирование CGLIB.

VB_ 25.04.2018 10:59

@dur вау! Ты прав, не знал этого. Может я читал устаревшие статьи. Я попробую это сделать в течение следующих нескольких часов. В любом случае, спасибо вам большое!

VB_ 25.04.2018 12:35

@dur, даже после перемещения аннотаций на уровень интерфейса, прокси-сервер mockito не имеет проверок безопасности.

VB_ 25.04.2018 12:48

@dur MockBean не помог

VB_ 04.05.2018 16:27
0
9
177
1

Ответы 1

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

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

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("myProfile")
public class MyServiceIT {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void testMyService() {
        logger.info("testMyService");

        //user TestRestTemplate to call your service.
    }

}

Обновлено: в этом интеграционном тесте Spring загружается нормально. Это означает, что все аннотации для безопасности обрабатываются, и все bean-компоненты, необходимые для создания, создаются и правильно вводятся. Возможно, вам придется контролировать профиль Spring .... это можно сделать с помощью аннотации @ActiveProfiles("myProfile"), которую я только что добавил в пример.

это вариант, которого я стараюсь избегать. Если я буду тестировать на вашем пути - я должен протестировать и безопасность, и бизнес-логику MyService в одном месте.

VB_ 24.04.2018 16:57

Я начинаю думать, что мало кто сталкивался с этой проблемой. И нет навороченного решения. Это может означать, что это неправильный подход - покрыть сервисную безопасность такими тестами.

VB_ 24.04.2018 17:06

с другой стороны, предположим, что ваш сервис выполняет действительно тяжелую логику. Выполнение одного метода занимает 10-30 секунд. Теперь у вас около 30 ролей, и вы хотите протестировать каждый метод для каждой роли. На это уйдет довольно много времени.

VB_ 24.04.2018 17:11

Можете ли вы замкнуть логику? Я ненавижу встраивать тестовые сценарии в бизнес-логику, но, возможно, если это будет сделано элегантно, это будет не слишком пренебрежительно.

Jose Martinez 24.04.2018 17:13

Я просто имею в виду, что при общем интеграционном тесте вы будете тестировать каждую конечную точку, скажем, в нескольких случаях. Если вы собираетесь тестировать безопасность - количество тестовых вызовов будет умножено на количество ролей / полномочий. Но интеграционный тест - вещь довольно тяжелая. Не знаю, чем здесь поможет бизнес-логика (

VB_ 24.04.2018 17:16

Раньше мы создавали интерфейс для всех наших классов обслуживания. Затем мы сделали бы для него импл. Что, если вы сделаете то же самое, и у вас может быть имплант, в котором есть только аннотации безопасности, а затем внедрить этот пустой имплант безопасности вашего интерфейса службы?

Jose Martinez 24.04.2018 17:20

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

VB_ 24.04.2018 17:24

Другие вопросы по теме