2016-03-23 4 views
2

В настоящее время я пытаюсь написать тестовый класс интеграции, в котором используются репозитории Spring Data Mongo. Я использую встроенный экземпляр Mongo, предоставляемый зависимостью de.flapdoodle.embed.mongo. Документация Spring Data указывает, что нам нужно только поставить эту зависимость в проекте, а EmbedMongoAutoConfiguration позаботится об остальном.Использовать Spring Data random (embedded) Монгольский порт с NoSQL JUnit @Rule

На данный момент это нормально, и установка порта на 0 делает процесс автоматической настройки, чтобы найти свободный порт для запуска экземпляра mongo.

Эта функция необходима для предотвращения столкновения с другими тестами (которые выполняются на сервере Jenkins CI вместе с другим проектом моей компании).

Проблема возникает сейчас, я хочу иметь возможность вставлять некоторые тестовые данные из какого-либо внешнего файла перед запуском каждого из моих тестовых методов. Я узнал, что NoSQL Unit может сделать это с помощью простой аннотации метода и JUnit @Rule.

Вот пример:

@Value("${local.mongo.port}") 
private int mongoPort; // <- still 0 a the time the Rule below is created. 

@Rule 
public MongoDbRule managedMongoDb = new MongoDbRule(MongoDbConfigurationBuilder.mongoDb().databaseName("myAwesomeDb").port(mongoPort).build()); 

@Test 
@UsingDataSet(locations = "testdata.json", loadStrategy = LoadStrategyEnum.CLEAN_INSERT) 
public void testMyData() { 
    // ... 
} 

Моя проблема заключается в том, что, то @Rule нужен порт Монго в его строителе для конкретизации, лежащей в основе MongoClient, но в то время @Rule конкретизируется, контекст Весны не полностью инициализирован, а EmbeddedMongoAutoConfiguration еще не опубликовал порт.

Так что мой вопрос, есть ли кто-нибудь когда-либо использовал функцию встроенного Монго с NoSQL Unit, и есть ли способ, чтобы, например, создать @Ruleпосле контекста Spring инициализируется?

мне было интересно, если найти свободный порт сам (статически), установив его в @Rule, а затем сказать EmbeddedMongoAutoConfiguration использовать его переопределение IMongodConfig фасоль была хорошая идея? или есть «более простой» способ?

Примечание: Я только что видел, что библиотека чепухи обеспечивает класс и статический метод, чтобы найти свободный порт сервера и его используют весной, как это:

Network.getFreeServerPort(getHost()), Network.localhostIsIPv6())) 

Спасибо всего заранее!

EDIT: Я пробовал решение, о котором я говорил чуть выше, и, похоже, он работает, хотя я все еще думаю, что он немного «подробный» и грязный.

private static final Logger log = LoggerFactory.getLogger(MyAwesomeIT.class); 
private static int mongoPort; 
static { 
    try { 
     mongoPort = Network.getFreeServerPort(); 
    } catch (IOException e) { 
     log.error("Error while trying to find a free port for Mongo", e); 
     mongoPort = -1; // test should then not work 
    } 
} 

@Rule 
public MongoDbRule managedMongoDb = new MongoDbRule(MongoDbConfigurationBuilder.mongoDb().databaseName("myAwesomeDb").port(mongoPort).build()); 

затем в соответствующем классе конфигурации:

@Configuration 
@EnableAutoConfiguration 
@EnableMongoRepositories 
@EnableConfigurationProperties(MongoProperties.class) 
static class ContextConfiguration { 
    @Autowired 
    private MongoProperties mongoProperties; 

    @PostConstruct 
    public void init() { 
     // Here, I override the port property 
     mongoProperties.setPort(mongoPort); 
    } 
} 

ответ

3

У меня была такая же проблема, и это было мое решение

 

@Configuration 
public class EmbeddedMongoConfig extends AbstractMongoConfiguration { 

    @Autowired 
    private Environment environment; 

    @Autowired 
    private MongoProperties properties; 

    @Autowired(required = false) 
    private MongoClientOptions options; 

    @Override 
    protected String getDatabaseName() { 
     return properties.getDatabase(); 
    } 

    @Override 
    @Bean(destroyMethod = "close") 
    public Mongo mongo() throws Exception { 
     properties.setPort(Network.getFreeServerPort()); 
     return properties.createMongoClient(this.options, this.environment); 
    } 

} 

 

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = { AppRunner.class, EmbeddedMongoConfig.class }) 
public class BaseTest { 

} 

 

public class CategoryServiceTest extends BaseTest{ 

    @Autowired 
    private CategoryService categoryService; 

    @Test 
    public void someTest(){ 
     fail("Test not implemented"); 
    } 

} 

+0

Это берет мою фактическую конфигурацию, она не принимает конфигурацию от класса EmbeddedMongoConfig. – devanathan

2

Доработка решение дается @ user6599111, можно получить port случайным образом выбран Flapdoodle Embedded Mongo, просто впрыскивая объект типа IMongodConfig.

Spring Boot строит автоматически этот объект для вас, как указано here.

Тогда класс конфигурации станет следующим.

@Configuration 
@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class }) 
public class MongoConfiguration { 
    @Autowired 
    private Environment environment; 

    @Autowired 
    private MongoProperties properties; 

    @Autowired(required = false) 
    private MongoClientOptions options; 

    @Autowired 
    private IMongodConfig mongoConfig; 

    @Bean 
    public MongoClient mongo() throws Exception { 
     properties.setPort(mongoConfig.net().getPort()); 
     return properties.createMongoClient(this.options, this.environment); 
    } 
} 
Смежные вопросы