Как написать пример модульного теста для Классов, аннотированных с помощью @Configuration в приложении Spring Boot - PullRequest
1 голос
/ 11 февраля 2020

У меня есть Класс конфигурации , который создает компонент для RedissonClient, а также создает CacheManager. Как создать блок модульного теста для классов конфигурации.

  1. Можем ли мы написать пример модульного теста для @Configuration класса?
  2. Если сможем, Как нам развиваться.

Я предпочитаю писать контрольный пример в Spock Framework с Groovy. Если нет, используйте Junit или Mockito Framework. Как написать пример модульного теста для классов, помеченных @Configuration в приложении Spring Boot

@Configuration
public class CacheConfiguration {
    private static final String CONFIG= "Configuration";

    @Value("${redis.server.url}")
    private String redisUrl;

    @Value("${redis.server.password}")
    private String password;

    @Bean 
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer().setAddress(redisUrl).setPassword(password);
        RedissonClient client = Redisson.create(config);
        return client;
    }
    @Bean
    public CacheManager redissonCacheManager(RedissonClient redissonClient) {
        Map<String, CacheConfig> config = new HashMap<String, CacheConfig>();
        config.put(CONFIG, new CacheConfig(24*60*1000, 12*60*1000));
        return new RedissonSpringCacheManager(redissonClient, config);
    }

}

Ответы [ 2 ]

1 голос
/ 12 февраля 2020

Я думаю, вы должны понимать, что классы, отмеченные @Configuration, на самом деле не являются java классами, или, по крайней мере, вы не должны относиться к ним так. Я знаю, это звучит неоднозначно, я объясню ...

Так что исторически Spring использовал XML конфигурации для объявления bean-компонентов.

Весной 2.5, я думаю, они ввели аннотацию на основе метод, в котором вы помещаете аннотации @Component / @Service в классы, помещаете @Autowired в любое место, куда вы хотите, чтобы spring вставляла зависимости, затем запускается Spring, сканирует путь к классам, обнаруживает компоненты и запускает контекст приложения с этими компонентами.

Затем в Spring 3.0 появился Java способ конфигурации связанных с пружиной конфигураций : @Configuration / @Bean в специальном классе.

Таким образом, вы должны рассматривать эти классы конфигурации как " подстановка "к методам, которые я описал ранее

Теперь позвольте мне спросить, как вы думаете, вы должны протестировать и XML конфигурацию бина самостоятельно? Вероятно, нет ... Как вы думаете, вы должны проверить, что класс имеет аннотацию @Component, и все необходимые зависимости автоматически подключены (с отражением или чем-то еще)? Наверное, нет.

Так почему вы хотите протестировать классы Java Config?

Вот еще один аргумент, который может вас заинтересовать

I Я сказал, что эти классы предназначены только для весны, чтобы разрешить бины, и он внутренне их запускает. Но Spring не просто «запускает» их - он создает оболочку времени выполнения, чтобы преодолеть некоторые технические особенности. Вот пример одной такой вещи:

Предположим, у нас есть три компонента: A, B, C, такие как B и C, зависят от A.


class A {}

class B {
   private A a;
   public B(A a) {this.a = a;}
}

class C {
   private A a;
   public C(A a) {this.a = a;}
}

Все ожидается, что bean-компоненты будут одиночными, поэтому мы определяем конфигурацию следующим образом:

@Configuration
public class MyConfig { 
   @Bean
   public A a() { return new A(); }

   @Bean
   public B b() { return new B(a()); }

   public C c() {return new C(a()); }

} 

Обратите внимание, что мы вызываем a() в определениях B и C Теперь позвольте мне задать вам вопрос: это "обычный" код java, как два разных вызова метода a() (в конструкторах B и C), соответственно, должны возвращать один и тот же экземпляр из A?

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

Я считаю, что есть и другие аргументы, подобные этому, но суть ясна - не тестируйте классы конфигурации на их own.

Вместо этого вы можете использовать интеграционный тест, который будет запускать подпружиненный контейнер и загружать все классы, необходимые в конфигурации. Тем не менее, в этом случае вы, вероятно, захотите смоделировать некоторые классы (например, с помощью @MockBean), чтобы тест не был на 100% точным.

С точки зрения покрытия кода - IMO, вам следует исключить эти классы из покрытия в целом

0 голосов
/ 13 февраля 2020

После некоторых исследований мы обнаружили, что можем запустить встроенный сервер Redis и проверить, можем ли мы подключиться к серверу Redis, раскрутив приложение. Я не знаю, правильно это или нет. Но для этого действительно требуется время, чтобы его завершить, это заняло около 20 секунд. Использовал следующую зависимость для проверки этой группы // https://mvnrepository.com/artifact/it.ozimov/embedded-redis testCompile: 'it.ozimov', имя: 'embedded-redis', версия: '0.7.2'

@SpringBootTest(classes = [TestApp])
class CacheConfigurationSpec extends Specification {

@Shared
RedisServer redisServer;

def setupSpec() {
    redisServer = RedisServer.builder()
            .port(6379)
            .setting("bind 127.0.0.1")
            .setting("maxmemory 128M")
            .build()
    redisServer.start()
}

def cleanupSpec() {
    if (redisServer != null) {
        redisServer.stop()
    }
}

@Autowired
private RedissonClient redissonClient;

def "load all contexts"() {

}
}
@SpringBootApplication
class TestApp {
 static void main(String[] args){
    SpringApplication.run(TestApp.class, args)
 }
}
...