Прежде всего, позвольте мне сказать громче, вам нужно спроектировать свой код так, чтобы он был тестируемым, чтобы вы тестировали свои личные поля с помощью открытых методов.
Но («но» — это причины, по которым люди все еще программируют, а не сам компьютер, так что будьте счастливы здесь), иногда вы хотите и должны изменить некоторые частные поля, чтобы проверить все возможные границы.
Часто закрытые поля можно изменить с помощью общедоступных методов получения и установки или с помощью конструктора классов, и в этих случаях тесты легко создавать, и все довольны.
Но когда вы используете внешние фреймворки, такие как Spring, может оказаться, что вы не можете контролировать внедренные приватные поля.
Я уже объяснял, как макетировать компоненты пружин в ваших тестах без необходимости поддержки и создания специальных конфигураций тестовых пружин в предыдущем посте, здесь я покажу вам, как изменить частную переменную для ваших тестов.
Пусть говорят код:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.google.common.collect.ImmutableSet; @Service public class SomeService { @Value ( "${whitelist.api.users:A,B,C}" ) private String apiUsers; private ImmutableSet<String> acceptableAPIBUsers; @PostConstruct public void init() { acceptableAPIBUsers = ImmutableSet.copyOf(apiUsers.replaceAll( " " , "" ).split( "," )); } public boolean isAnAcceptableUser(String user) { return user == null ? false : acceptableAPIBUsers.contains(user.toUpperCase()); } } |
У нас нет контроля над строкой apiUsers, поэтому у нас есть несколько простых опций, одна из которых — создать конфигурацию Spring для вашего теста, изменить контекст Spring и смоделировать свойство, а вторая — создать установщик для изменения значения собственность из вашего теста.
Я не рекомендую создавать общедоступные оценщики только для ваших тестов, так как это может сбивать с толку других людей, которые смотрят на ваш код, и создание и поддержка конфигураций Spring для ваших тестов может быть трудной задачей.
Я знаю, что вы думаете: «Если я не смогу сделать что-либо из вышеперечисленного, меня уволят, моя девушка бросит меня, и моя жизнь закончится», но не беспокойтесь, я здесь, чтобы показать вам другой вариант!
Вы можете создать класс с классическим методом для оценки вашего личного поля в тесте:
1
2
3
4
5
6
7
8
|
import groovy.transform.CompileStatic @CompileStatic class SomeServiceAccessor { public static void setApiUsers(SomeService someService,String apiUsers){ someService. @apiUsers = apiUsers } } |
И используйте его в своем модульном тесте:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import org.junit.Before; import org.junit.Test; public class SomeServiceTest { private SomeService service; @Before public void setUp() { service = new SomeSercvice(); SomeSercviceAccessor.setApiUsers(service, "pippo,pluto,bungabunga" ); service.init(); } @Test public void testIsNotApiUser() { assertThat(service.isAnRTBUser( "" ), is( false )); assertThat(service.isAnRTBUser( null ), is( false )); assertThat(service.isAnRTBUser( "random" ), is( false )); } @Test public void testIsRTBUser() { assertThat(service.isAnRTBUser( "pippo" ), is( true )); assertThat(service.isAnRTBUser( "PIPPO" ), is( true )); assertThat(service.isAnRTBUser( "pluto" ), is( true )); assertThat(service.isAnRTBUser( "bungabunga" ), is( true )); } } |
Конечно, вы можете сделать то же самое в java, изменив видимость поля с помощью отражения, но я думаю, что отличное решение может быть чище и проще.
Теперь я закончу этот пост следующей рекомендацией:
Не используйте это решение, если вам действительно не нужно изменять частные переменные для модульного тестирования вашего класса!