As per
docs, under (Expecting Log Messages),
Be sure to exchange the default logger with the TestEventListener in your application.conf to enable this function:
akka.loggers = [akka.testkit.TestEventListener]
So, this works well when I put it in application.conf. My test work well
@Test
public void testActorForNonExistentLocation() throws Exception {
final Map<String, String> configValues = Collections.singletonMap("tenant.assetsLocation",
"/non/existentLocation");
final Config config = mergeConfig(configValues);
System.out.println(config.getList("akka.loggers"));
new JavaTestKit(system) {{
final Props props = TenantMonitorActor.props(config);
final ActorRef supervisor = system.actorOf(props, "supervisor");
new EventFilter<Void>(DiskException.class) {
@Override
protected Void run() {
supervisor.tell(new TenantMonitorMessage(), supervisor);
return null;
}
}.from("akka://system/user/supervisor/diskMonitor").occurrences(1).exec();
}};
}
Now when I try to run my application
public class Main {
private Main() {
}
public static void main(final String[] args) {
final Config config = ConfigFactory.load();
final ActorSystem actorSystem = ActorSystem.create(config.getString("
ec.name"));
setUpMonitoring(actorSystem, config);
}
private static void setUpMonitoring(final ActorSystem system, final Config config) {
final ActorRef tenantMonitorRef = system.actorOf(TenantMonitorActor.props(config),
"tenantMonitor");
tenantMonitorRef.tell(new TenantMonitorMessage(), tenantMonitorRef);
}
}
I see errors as
error while starting up loggers
akka.ConfigurationException: Logger specified in config can't be loaded [akka.testkit.TestEventListener] due to [java.lang.ClassNotFoundException: akka.testkit.TestEventListener]
at akka.event.LoggingBus$$anonfun$4$$anonfun$apply$1.applyOrElse(Logging.scala:116)
at akka.event.LoggingBus$$anonfun$4$$anonfun$apply$1.applyOrElse(Logging.scala:115)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36)
at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:215)
at scala.util.Try$.apply(Try.scala:191)
at scala.util.Failure.recover(Try.scala:215)
at akka.event.LoggingBus$$anonfun$4.apply(Logging.scala:115)
at akka.event.LoggingBus$$anonfun$4.apply(Logging.scala:110)
at scala.collection.TraversableLike$WithFilter$$anonfun$map$2.apply(TraversableLike.scala:728)
at scala.collection.Iterator$class.foreach(Iterator.scala:750)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1202)
at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
at scala.collection.TraversableLike$WithFilter.map(TraversableLike.scala:727)
at akka.event.LoggingBus$class.startDefaultLoggers(Logging.scala:110)
at akka.event.EventStream.startDefaultLoggers(EventStream.scala:26)
at akka.actor.LocalActorRefProvider.init(ActorRefProvider.scala:622)
at akka.actor.ActorSystemImpl.liftedTree2$1(ActorSystem.scala:619)
at akka.actor.ActorSystemImpl._start$lzycompute(ActorSystem.scala:616)
at akka.actor.ActorSystemImpl._start(ActorSystem.scala:616)
at akka.actor.ActorSystemImpl.start(ActorSystem.scala:633)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:142)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:109)
at akka.actor.ActorSystem$.create(ActorSystem.scala:57)
at akka.actor.ActorSystem.create(ActorSystem.scala)
at Main.main(Main.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ClassNotFoundException: akka.testkit.TestEventListener
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at akka.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:67)
at akka.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:66)
at scala.util.Try$.apply(Try.scala:191)
at akka.actor.ReflectiveDynamicAccess.getClassFor(DynamicAccess.scala:66)
at akka.event.LoggingBus$$anonfun$4.apply(Logging.scala:113)
... 24 more
Exception in thread "main" akka.ConfigurationException: Could not start logger due to [akka.ConfigurationException: Logger specified in config can't be loaded [akka.testkit.TestEventListener] due to [java.lang.ClassNotFoundException: akka.testkit.TestEventListener]]
at akka.event.LoggingBus$class.startDefaultLoggers(Logging.scala:144)
at akka.event.EventStream.startDefaultLoggers(EventStream.scala:26)
at akka.actor.LocalActorRefProvider.init(ActorRefProvider.scala:622)
at akka.actor.ActorSystemImpl.liftedTree2$1(ActorSystem.scala:619)
at akka.actor.ActorSystemImpl._start$lzycompute(ActorSystem.scala:616)
at akka.actor.ActorSystemImpl._start(ActorSystem.scala:616)
at akka.actor.ActorSystemImpl.start(ActorSystem.scala:633)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:142)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:109)
at akka.actor.ActorSystem$.create(ActorSystem.scala:57)
at akka.actor.ActorSystem.create(ActorSystem.scala)
at Main.main(Main.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
My application.conf looks like
akka {
event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
loglevel = "INFO"
loggers = [akka.testkit.TestEventListener]
}
ec {
name = "Connector"
}
tenant {
assetsLocation: /Users
}
monitoring {
tenant.disk.schedule.seconds: 2
tenant.disk.threshold.percent: 80
}
and I have the dependency installed as well
<dependencies>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_2.11</artifactId>
<version>${akka-actor_2.11.version}</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-testkit_2.11</artifactId>
<version>${akka-testkit_2.11.version}</version>
</dependency>
</dependencies>
<akka-actor_2.11.version>2.3.9</akka-actor_2.11.version>
<akka-testkit_2.11.version>2.3.10</akka-testkit_2.11.version>
Where is bug/inconsistency?
This may not be a bug at all and difference in understanding.
We use maven scope to decide which dependencies should be available and when. Usually with tests, we use <scope>test</scope> to make the dependency available only in test and not in final application jar when bundled. Now if we make use of this kind of tests(Expecting Log Messages), we need to remove <scope>test</scope> to let the application run correctly and tests pass at the same time. Which means that that dependency akka-testkit need to be present in the final jar as well since application.conf needs it to load akka.testkit.TestEventListener.
This if all sounds correct, couples production and test code together and is required in current setup.
Again, I may have missed something very basic here, but the only way I could run the application and let the test pass is by combining the dependencies aka-actor and akka-testkit together.
What are your thoughts?