Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
10-27-2021 07:28 PM
I have created some Neo4j procedures. I inject a Log using the @Context annotation. I pass the Log through the call chain to other methods so I can log within those methods. This works fine. I now want to unit test the methods independently, which requires a Log to be passed in the method calls. How do I create a Logger that is compatible with the neo4j Log (which is an interface) that is injected by the @Context annotation?
01-10-2022 04:54 AM
I have the very same issue and question. Did you end up finding a solution?
01-10-2022 06:09 AM
Maybe you can try with something similar to what was done in the APOC, neo4j-apoc-procedures/CypherProceduresStorageTest.java at ad48af6a7dde19825d7fcc100fd2c0612536289d ·... .
That is:
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.neo4j.configuration.GraphDatabaseSettings;
import org.neo4j.dbms.api.DatabaseManagementService;
import org.neo4j.exceptions.KernelException;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.kernel.api.procedure.GlobalProcedures;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.test.TestDatabaseManagementServiceBuilder;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.assertFalse;
public class CypherProceduresStorageTest {
@Rule
public TemporaryFolder STORE_DIR = new TemporaryFolder();
private GraphDatabaseService db;
@Before
public void setUp() throws Exception {
DatabaseManagementService databaseManagementService = new TestDatabaseManagementServiceBuilder(STORE_DIR.getRoot().toPath()).build();
db = databaseManagementService.database(GraphDatabaseSettings.DEFAULT_DATABASE_NAME);
// register the procedure class
registerProcedure(db, CypherProcedures.class);
}
@Test
public void testIssue1744() throws Exception {
// call my procedure
db.executeTransactionally("CALL my.procedure");
// get entire file as string
final String logFileContent = Files.readString(Path.of(STORE_DIR.getRoot().getPath(), "logs" , "debug.log"));
// assertions...
assertFalse(logFileContent.contains("Could not register function: custom.vantagepoint_within_area"));
}
// from https://github.com/neo4j-contrib/neo4j-apoc-procedures/blob/4.3/test-utils/src/main/java/apoc/util/TestUtil.java
public static void registerProcedure(GraphDatabaseService db, Class<?>...procedures) {
GlobalProcedures globalProcedures = ((GraphDatabaseAPI) db).getDependencyResolver().resolveDependency(GlobalProcedures.class);
for (Class<?> procedure : procedures) {
try {
globalProcedures.registerProcedure(procedure, true);
globalProcedures.registerFunction(procedure, true);
globalProcedures.registerAggregationFunction(procedure, true);
} catch (KernelException e) {
throw new RuntimeException("while registering " + procedure, e);
}
}
}
}
01-10-2022 06:43 AM
Thanks for the response. We - at least I - actually need a Log
object pass it to the methods we test. We talk about unit testing instead of integration testing here. But perhaps this is not the intended way to do it in Neo4j?
I actually had some success in the meantime. I managed to create a LogProvider and get a logger from it like so:
Log4jLogProvider log4jLogProvider = new Log4jLogProvider(LogConfig.createBuilder(System.out, Level.INFO)
.withFormat(PLAIN)
.withCategory(false)
.build());
log = log4jLogProvider.getLog(ExtensionClass.class);
In this way, the logger can now be passed to the tested methods or the extension as a whole.
All the sessions of the conference are now available online