无法使用NoSqlUnit访问内存中的mongodb

无法使用NoSqlUnit访问内存中的mongodb,mongodb,junit,nosql,jboss-arquillian,microprofile,Mongodb,Junit,Nosql,Jboss Arquillian,Microprofile,我有一个arquillian组件测试,我想使用一个使用NoSqlUnit的内存MongoDB(Fongo)数据库。我使用@Producer来定义我的数据存储连接,并在JavaSE8上使用Eclipse微文件 问题是,在启动内存中的DB之后,在执行端点测试时,我无法在代码中以编程方式访问它 我有一个DataStoreConnectionProducer: import javax.enterprise.context.ApplicationScoped; import javax.enterpri

我有一个arquillian组件测试,我想使用一个使用NoSqlUnit的内存MongoDB(Fongo)数据库。我使用@Producer来定义我的数据存储连接,并在JavaSE8上使用Eclipse微文件

问题是,在启动内存中的DB之后,在执行端点测试时,我无法在代码中以编程方式访问它

我有一个DataStoreConnectionProducer:

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;


@ApplicationScoped
public class DataStoreConnectionProducer {
    private MongoClient mongoClient;

    private static final Config config = ConfigProvider.getConfig();

    @Produces
    public MongoDatabase createMongoClient(){
        final String DB_PATH    = config.getValue( "mongodb.path", String.class );
        final int DB_PORT       = config.getValue( "mongodb.port", Integer.class );
        final String DB_NAME    = config.getValue( "mongodb.dbname", String.class );

        if( DB_NAME.equals( "test" ) )
            return new MongoClient().getDatabase(DB_NAME);
        else
            return new MongoClient( DB_PATH, DB_PORT ).getDatabase( DB_NAME );

    }
}
我的问候刀正在注射MongoDatabase

@Inject MongoDatabase mongoDatabase;
我的资源如下所示:

@Path( "/greetings" )
public class HelloResource {

    @Inject
    private GreetingDAO greetingDAO;

    @Inject
    private GreetingService greetingService;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getGreeting (){
        return Response.ok(greetingDAO.findAll(), MediaType.APPLICATION_JSON).build();
    }

    @GET
    @Path( "{id}" )
    @Produces( MediaType.APPLICATION_JSON )
    public Response getGreetingById( @PathParam( "id" ) String greetingId ){
        try {
            return Response.ok( greetingDAO.findByID( greetingId.toLowerCase() ), MediaType.APPLICATION_JSON ).build();
        }catch ( NoSuchElementException ex ){
            ex.printStackTrace();
            return Response.status( 404 ).build();
        }
    }
最后,我的阿奎利安测试:

    @RunWith( Arquillian.class )
    @RunAsClient
    public class HelloResourceTest extends AbstractTest{

        private static final String DB_NAME     = "test";

        @ClassRule
        public static final InMemoryMongoDb inMemoryMongoDb =
                newInMemoryMongoDbRule().targetPath( "localhost" ).build();
        @Rule
        public MongoDbRule embeddedMongoDbRule = newMongoDbRule()
                .defaultEmbeddedMongoDb(DB_NAME);

        @Inject MongoClient mongoClient;

        @Deployment
        public static WebArchive createDeployment () {
            WebArchive war = createBasicDeployment()
                    .addClasses(
                        HelloResource.class,
                        GreetingDAO.class,
                        GreetingService.class,
                        Greeting.class,
                        DAO.class,
                        DataStoreConnectionProducer.class
                    );
            System.out.println( war.toString(true) );
            return war;
        }

        private MongoDatabase getFongoDataBase(){
            return mongoClient.getDatabase( DB_NAME );
        }
这就是我开始感到困惑的地方。。知道Fongo是一个内存数据库,肯定没有远程方式访问它?相反,我肯定必须将其提供给我的DataStoreConnectionProducer,或者以某种方式将其注入我的GreetingDAO,以便使用FongDB,而不是@Producer尝试连接到我的托管MongoDB

您可能会问:为什么不使用托管MongoDB?
回答:因为我希望进行基于组件的测试,而不是集成测试。

好的,在@lordofjars的指导下,我设法使用NoSQLUnit和内存MongoDB(Fongo)进行资源测试

不过,我不得不做一些更改:

数据存储连接生产者 它做了它应该做的,但是在它的实现中不是很可测试,我让它更详细一些:

@Singleton
public class DataStoreConnectionFactory {
    private MongoDatabase mongoDatabase;


    @PostConstruct
    public void init(){
        this.mongoDatabase = establishConnection();
    }

    protected MongoDatabase establishConnection(){
        final Config config = ConfigProvider.getConfig();
        final String DB_PATH    = config.getValue( "mongodb.path", String.class );
        final int DB_PORT       = config.getValue( "mongodb.port", Integer.class );
        final String DB_NAME    = config.getValue( "mongodb.dbname", String.class );

        return new MongoClient( DB_PATH, DB_PORT ).getDatabase( DB_NAME );
    }

    @Produces
    public MongoDatabase getMongoDatabase(){
        return this.mongoDatabase;
    }

}
我还创建了该生产者/工厂的模拟版本,并将其添加到我的测试路径中,如下所示:

@Singleton
@Alternative
public class FakeDataStoreConnectionFactory {
    private MongoDatabase mongoDatabase;


    @PostConstruct
    public void init(){
        this.mongoDatabase = establishConnection();
    }

    protected MongoDatabase establishConnection(){
        return Mockito.mock(MongoDatabase.class);
    }

    @Produces
    public MongoDatabase getMongoDatabase(){
        return this.mongoDatabase;
    }

    public void setMongoDatabase(MongoDatabase db){
        this.mongoDatabase = db;
    }

}
然后,我们将test-beans.xml定义为:

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                      http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
        bean-discovery-mode="all">

    <alternatives>
        <class>path.to.my.test.folder.containing.FakeDataStoreConnectionFactory</class>
    </alternatives>
</beans>
@注入 FakeDataStoreConnectionFactory FakeDataStoreConnectionFactory

@Before
public void setupTest(){
    fakeDataStoreConnectionFactory.setMongoDatabase( mongoDbRule.getDatabaseOperation().connectionManager().getDatabase( "test" ) );

}
}


我现在面临的唯一问题是@UsingDataSet注释拒绝找到我的.json文件,它们位于/path/to/my/test/file/initData.json下。无论我把它们放在哪里,它仍然不起作用。

是的,您是对的,Fongo不提供任何使用网络访问它的方法,而只提供使用对创建的内存Java实例的访问。您可以尝试在src/test/Java上创建一个名为FongDataStoreConnectionProducer的类,该类创建Fongo实例。但是,您将无法使用NoSQLUnit,因为这两个实例是不同的。另一种选择可能是创建一个静态工厂并使用嵌入式容器,以便它们可以共享相同的JVM,但真正的解决方案可能是以另一种方式解决问题,使用NoSQLUnit创建测试并仅使用GreetingDAO类(在CDI之外,Arquillian,…)然后创建另一个测试,使用Arquillian Cube启动一个真正的MongoDB服务器。我已经取得了一些“进展”,因为我知道@RunAsClient实际上抽象了所有底层部署,所以我无法为我的DataStoreConnectionProducer设置任何值。但是现在,当我尝试执行
@Inject MongoClient fongoClient
时,我得到了类型MongoClient的
未满足的依赖性。
我猜容器CDI注入与内存数据库的@Inject相冲突。NoSqlUnit有没有办法在Arquillian使用Fongo?我会用代码更新我的问题changes@lordofthejars我明白了,如果您可以从顶部(资源)到底部(持久性)进行完整的组件测试,同时获得内存中数据库(如fongo)的灵活性和速度,那就太好了。但我会尝试采取另一种方法来解决这个问题。谢谢基本上,问题是你在容器中部署了一些东西。您可以做的另一件事是不运行RunAsClient,所以在容器中运行,并在结果war中绑定NoSQLUnit+Fongo。如果你给我提供一个github项目,我可以试着去做。分叉和检查:)很乐意帮忙,它也帮助我改进了APE。
@Before
public void setupTest(){
    fakeDataStoreConnectionFactory.setMongoDatabase( mongoDbRule.getDatabaseOperation().connectionManager().getDatabase( "test" ) );

}