2016-04-22 4 views
0

Я пытаюсь улучшить знание Spring, читая Spring в действии 4. Когда я должен перейти к разделу, описывая использование аннотации Qualifier (3.3.2), я столкнулся с проблемой. Чтобы проверить эту аннотацию в действии, я написал интерфейс Dessert, который реализован тремя классами, создавая в контексте с помощью аннотации @Component. Я также создал класс Taster, который «на вкус» немного десерта, автоподстроенный некоторым квалификатором. Когда я запускаю свое приложение, используя AnnotationConfigApplicationContext - все работает хорошо. С SpringJUnit4ClassRunner - это не так. Думаю, я пропустил что-то в своем тестовом коде, но у меня недостаточно знаний, чтобы понять, что. Интерфейс:@Qualifier не работает в Junit4

package bakery.intrface; 
@FunctionalInterface 
public interface Dessert { 
    void introduce(); 
} 

Cake:

package bakery.desserts; 

import bakery.intrface.Dessert; 
import org.springframework.stereotype.Component; 

@Component 
public class Cake implements Dessert { 
    @Override 
    public void introduce() { 
     System.out.println("I am a cake!"); 
    } 
} 

Cookie:

package bakery.desserts; 

import bakery.intrface.Dessert; 
import org.springframework.stereotype.Component; 

@Component 
public class Cookie implements Dessert { 
    @Override 
    public void introduce() { 
     System.out.println("I'm a cookie!"); 
    } 
} 

Мороженое:

package bakery.desserts; 

import bakery.intrface.Dessert; 
import org.springframework.stereotype.Component; 

@Component 
public class IceCream implements Dessert { 
    @Override 
    public void introduce() { 
     System.out.println("I'm an ice cream!"); 
    } 
} 

Класс, потребляет немного фасоли, Taster:

package bakery; 

import bakery.intrface.Dessert; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.stereotype.Component; 

@Component 
public class Taster { 

    private Dessert dessert; 

    public void taste(){ 
     dessert.introduce(); 
    } 

    @Autowired 
    @Qualifier("iceCream") 
    public void setDessert(Dessert dessert) { 
     this.dessert = dessert; 
    } 
} 

Конфигурация:

package bakery.config; 

import bakery.Bakery; 
import bakery.Taster; 
import bakery.desserts.Cake; 
import bakery.intrface.Dessert; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 

@ComponentScan(basePackageClasses = Bakery.class) 
public class BakeryConfig { 
} 

Run Класс:

package bakery; 

import bakery.config.BakeryConfig; 
import org.springframework.context.annotation.AnnotationConfigApplicationContext; 

public class Bakery { 
    public static void main(String[] args) { 
     AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BakeryConfig.class); 
     String[] beans = context.getBeanDefinitionNames(); 
     Taster taster = (Taster) context.getBean("taster"); 
     taster.taste(); 
    } 
} 

испытаний Класс:

package bakery; 

import bakery.config.BakeryConfig; 
import bakery.intrface.Dessert; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

import static org.junit.Assert.assertNotNull; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = BakeryConfig.class) 
public class BakeryTest { 

    @Autowired 
    Dessert dessert; 

    @Autowired 
    Taster taster; 

    @Test 
    public void contextInit(){ 
     assertNotNull(dessert); 
     dessert.introduce(); 
    } 

    @Test 
    public void tasterInit(){ 
     assertNotNull(taster); 
    } 
} 

Когда я запускаю тест, я получаю исключение: Нет квалификационная bean типа [bakery.intrface.Dessert]: ожидаемое одно совпадение b ean, но нашел 3: cookie, iceCream, торт.

ответ

2

В вашем контексте приложения есть 3 «десертных» компонента, вы должны указать, какой из них вы хотите подключить.

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = BakeryConfig.class) 
public class BakeryTest { 

    @Autowired 
    @Qualifier("iceCream") // <===================== you must specify which bean to be wired 
    Dessert dessert; 

    @Autowired 
    Taster taster; 
+0

Это сработало! Я был настолько глуп, чтобы забыть квалифицировать еще один случай с десертом в моем коде, спасибо. –

1

Этого можно ожидать.

Декларация

@Autowired 
Dessert dessert; 

просит для Dessert объекта. Dessert - интерфейс, и есть три реализующих класса: Cookie, IceCream и Cake. Поскольку вы не сделали более явным, какую из этих реализаций вы хотите, Spring выдает ошибку, потому что не может решить, что делать.

Если вам это в тесте, вы можете выполнить одно из следующих действий:

@Autowired 
@Qualifier("iceCream") 
Dessert dessert; 

получить только мороженое десерт,

ИЛИ

@Autowired 
List<Dessert> desserts; 

в получить список, содержащий все реализации.

+0

Благодарим вас за ответ. Я не знал о возможности инъекции всех компонентов, определенных в контексте как список. –

Смежные вопросы