I would like to test a singleton actor using java in Scala IDE build of Eclipse SDK (Build id: 3.0.2-vfinal-20131028-1923-Typesafe) and Akka is 2.3.1.
public class WorkerTest {
static ActorSystem system;
#BeforeClass
public static void setup() {
system = ActorSystem.create("ClusterSystem");
}
#AfterClass
public static void teardown() {
JavaTestKit.shutdownActorSystem(system);
system = null;
}
#Test
public void testWorkers() throws Exception {
new JavaTestKit(system) {{
system.actorOf(ClusterSingletonManager.defaultProps(
Props.create(ClassSingleton.class), "class",
PoisonPill.getInstance(),"backend"), "classsingleton");
ActorRef selection = system.actorOf(ClusterSingletonProxy.defaultProps("user/classsingleton/class", "backend"), "proxy");
System.out.println(selection);
}};
}
}
the ClassSingleton.java:
public class ClassSingleton extends UntypedActor {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
public ClassSingleton() {
System.out.println("Constructor is done");
}
public static Props props() {
return Props.create(ClassOperator.class);
}
#Override
public void preStart() throws Exception {
ActorRef selection = getSelf();
System.out.println("ClassSingleton ActorRef... " + selection);
}
#Override
public void onReceive(Object message) {
}
#Override
public void postStop() throws Exception {
System.out.println("postStop ... ");
}
}
The ClassSingleton actor is doing nothing, the printout is:
Actor[akka://ClusterSystem/user/proxy#-893814405] only, which is printed from the ClusterSingletonProxy. No exception and Junit is done, green flag. In debugging ClassSingleton is not called (including contructor and preStart()). Sure it is me, but what is the mistake? Even more confusing that the same ClassSingleton ClusterSingletonManager code is working fine outside of javatestkit and junit.
I suspect that the cluster setup might be reponsible, so I tried to include and exclude the following code (no effect). However I would like to understand why we need it, if we need it (it is from an example code).
Many thanks for your help.
Address clusterAddress = Cluster.get(system).selfAddress();
Cluster.get(system).join(clusterAddress);
Proxy pattern standard behavior is to locate the oldest node and deploy the 'real' actor there and the proxy actors are started on all nodes. I suspect that the cluster configuration did not complete and thus why your actor never got started.
The join method makes the node to become a member of the cluster. So if no one joins the cluster the actor with proxy cannot be created.
The question is are your configuration files that are read during junit test have all the information to create a cluster? Seed-nodes? Is the port set to the same as the seed node?
Related
I'm going to read files from SFTP location line by line:
#Override
public void configure() {
from(sftpLocationUrl)
.routeId("route-name")
.split(body().tokenize("\n"))
.streaming()
.bean(service, "build")
.to(String.format("activemq:%s", queueName));
}
But this application will be deployed on two nodes, and I think that in this case, I can get an unstable and unpredictable application work because the same lines of the file can be read twice.
Is there a way to avoid such duplicates in this case?
Camel has some (experimental) clustering capabilities - see here.
In your particular case, you could model a route which is taking the leadership when starting the directory polling, preventing thereby other nodes from picking the (same or other) files.
soluion is active passive mode . “In active/passive mode, you have a single master instance polling for files, while all the other instances (slaves) are passive. For this strategy to work, some kind of locking mechanism must be in use to ensure that only the node holding the lock is the master and all other nodes are on standby.”
it can implement with hazelcast, consul or zookeper
public class FileConsumerRoute extends RouteBuilder {
private int delay;
private String name;
public FileConsumerRoute(String name, int delay) {
this.name = name;
this.delay = delay;
}
#Override
public void configure() throws Exception {
// read files from the shared directory
from("file:target/inbox" +
"?delete=true")
// setup route policy to be used
.routePolicyRef("myPolicy")
.log(name + " - Received file: ${file:name}")
.delay(delay)
.log(name + " - Done file: ${file:name}")
.to("file:target/outbox");
}}
ServerBar
public class ServerBar {
private Main main;
public static void main(String[] args) throws Exception {
ServerBar bar = new ServerBar();
bar.boot();
}
public void boot() throws Exception {
// setup the hazelcast route policy
ConsulRoutePolicy routePolicy = new ConsulRoutePolicy();
// the service names must be same in the foo and bar server
routePolicy.setServiceName("myLock");
routePolicy.setTtl(5);
main = new Main();
// bind the hazelcast route policy to the name myPolicy which we refer to from the route
main.bind("myPolicy", routePolicy);
// add the route and and let the route be named Bar and use a little delay when processing the files
main.addRouteBuilder(new FileConsumerRoute("Bar", 100));
main.run();
}
}
Server Foo
public class ServerFoo {
private Main main;
public static void main(String[] args) throws Exception {
ServerFoo foo = new ServerFoo();
foo.boot();
}
public void boot() throws Exception {
// setup the hazelcast route policy
ConsulRoutePolicy routePolicy = new ConsulRoutePolicy();
// the service names must be same in the foo and bar server
routePolicy.setServiceName("myLock");
routePolicy.setTtl(5);
main = new Main();
// bind the hazelcast route policy to the name myPolicy which we refer to from the route
main.bind("myPolicy", routePolicy);
// add the route and and let the route be named Bar and use a little delay when processing the files
main.addRouteBuilder(new FileConsumerRoute("Foo", 100));
main.run();
}}
Source : Camel In Action 2nd Edition
Is there a way to execute "AfterAllTests" action within JUnit 5? E.g. close connection to db, close embedded kafka cluster, etc.
P.S. There is a way to do some preconditions before all tests with help of extension like that:
public class BeforeAfterExtension implements BeforeAllCallback, AfterAllCallback {
private static boolean FLAG = Boolean.TRUE;
...
#Override
public void beforeAll(ExtensionContext extensionContext) {
log.info("~~~~~~~~~~~~~~~~~~ BeforeAll setup ~~~~~~~~~~~~~~~~~~");
if (FLAG) {
// some code here
FLAG = Boolean.FALSE;
}
}
#Override
public void afterAll(ExtensionContext extensionContext) {
// ??
}
But no way for "After" tasks.
Yes you can use below mentioned code.
#AfterAll
static void afterAllIAmCalled() {
System.out.println("---Inside after finishing all testsDownAll---");
}
Link for you: https://www.concretepage.com/testing/junit-5/junit-5-beforeall-and-afterall-example
Updating answer further based on your need of running after all sets. Define your tests in suite as shown below
#RunWith(Suite.class)
# Suite.SuiteClasses({
SuiteTest1.class,
SuiteTest2.class,
})
public class JunitTest {
// This class remains empty, it is used only as a holder for the above annotations but as you need to perform action at the end of it do as mentioned below
#AfterSuite
Private void methodName(){
//my suite end action
}
}
Replied on mobile. Might not be symmetric answer but will solve your problem.
This should work for you.
In my project mostly all imports relay on io.vertx.reactivex.core.Vertx package import, effectively makes whole project use reactivex (not core/vanilla) version of Vertx and it's verticles. I started to unit test a bit our application and to do so and to make it play nicely with JUint, according to this documentation following setup is needed to use JUnit and to run test cases in correct thread and verticle context:
#RunWith(VertxUnitRunner.class) /* Set the runner */
public class DaoTest {
#Rule /* Define rule to get vertx instance in test */
public RunTestOnContext rule = new RunTestOnContext();
#Test
public void exampleTest(TestContext context) {
TestClass t = new TestClass(rule.vertx());
}
}
the definition of TestClass is following:
import io.vertx.reactivex.core.Vertx; /* Mind here */
public class TestClass {
public TestClass(Vertx vertx) {
/* Something */
}
I'm unable to provide correct instance of Vertx because only one definition of RunTestOnContext exist in package io.vertx.ext.unit.junit and produces io.vertx.core.Vertx instance, which is incompatible with io.vertx.reactivex.core.Vertx that TestClass is using. Some other test utilities, like TestContext have their equivalents in reactivex packages io.vertx.reactivex.ext.unit.TestContext, but this seems not be a case for RunTestOnContext.
The question would be how to obtain correctly io.vertx.reactivex.core.Vertx instance in test context to still ensure thread and context consistency?
The vertx-unit project has only depdendency to vertx-core. And has no dependency to vertx-rx-java. And that is understandable. Therefore the RunTestOnContext is built using the io.vertx.core.Vertx as you see.
You can downcast with the vertx.getDelegate() from io.vertx.reactivex.core.Vertx to io.vertx.core.Vertx. Bu that doesnt work in the opposite direction.
Therefore your best option is to copy the code of the RunTestOnContext and create your reactivex version of it. (The fastest way is to just change the import to io.vertx.reactivex.core.Vertx and use the vertx.getDelegate() where it is accessed.)
Get RxVertx instance by rxVertx = Vertx.vertx(); & vertx instance by rxVertx.getDelegate();. Here is a full code snippet:
#RunWith(VertxUnitRunner.class)
public class MyVerticleTest {
protected Vertx vertx;
#Before
public void setUp(TestContext context) {
rxVertx = Vertx.vertx();
vertx = rxVertx.getDelegate();
Async async = context.async(1);
RxHelper.deployVerticle(rxVertx, new MyVerticle())
.subscribe(res -> async.countDown(), err -> {
throw new RuntimeException(err);
});
}
#Test
public void my_test(TestContext context) {
Async async = context.async();
rxVertx.eventBus().rxSend("address", dataToSend)
// .flatMap()
.subscribe(receivedData -> {
// assert what you want;
async.complete();
}, context::fail);
}
#After
public void tearDown(TestContext context) {
client.close();
rxVertx.close(context.asyncAssertSuccess());
}
}
Overview: There are instances where in I want to stop the running cucumber test pack midway -- say for example when x number of tests failed.
I can do this just fine but I want the json file (plugin = {json:...}) to be generated when the test stops. Is this doable?
What I've tried so far:
Debug and see where the reporting / plugin generation happens. It seems to be when this line executes:
Cucumber.java: runtime.getEventBus().send.....
#Override
protected Statement childrenInvoker(RunNotifier notifier) {
final Statement features = super.childrenInvoker(notifier);
return new Statement() {
#Override
public void evaluate() throws Throwable {
features.evaluate();
runtime.getEventBus().send(new TestRunFinished(runtime.getEventBus().getTime()));
runtime.printSummary();
}
};
}
I was hoping to access the runtime field but it has a private modifier. I also tried accessing it via reflections but I'm not exactly getting what I need.
Found a quite dirty, but working solution and got what I need. Posting my solution here in case anyone might need.
Create a custom cucumber runner implementation to take the runtime instance.
public final class Foo extends Cucumber {
static Runtime runtime;
/**
* Constructor called by JUnit.
*
* #param clazz the class with the #RunWith annotation.
* #throws IOException if there is a problem
* #throws InitializationError if there is another problem
*/
public Foo(Class clazz) throws InitializationError, IOException {
super(clazz);
}
#Override
protected Runtime createRuntime(ResourceLoader resourceLoader, ClassLoader classLoader, RuntimeOptions runtimeOptions) throws InitializationError, IOException {
runtime = super.createRuntime(resourceLoader, classLoader, runtimeOptions);
return runtime;
}
}
Call the same line that generates the file depending on the plugin used:
public final class ParentHook {
#Before
public void beforeScenario(Scenario myScenario) {
}
#After
public void afterScenario() {
if (your condition to stop the test) {
//custom handle to stop the test
myHandler.pleaseStop();
Foo.runtime.getEventBus().send(new TestRunFinished(Foo.runtime.getEventBus().getTime()));
}
}
}
This will however require you to run your test via Foo.class eg:
#RunWith(Foo.class) instead of #RunWith(Cucumber.class)
Not so much value here but it fits what I need at the moment. I hope Cucumber provides a way to do this out of the box. If there's a better way, please do post it here so I can accept your answer once verified.
Why not quit?
import cucumber.api.Scenario;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.When;
public class StepDefinitions {
private static int failureCount = 0;
private int threshold = 20;
#When("^something$")
public void do_something() {
// something
}
#After
public void after(Scenario s) {
if (s.isFailed()) ++failureCount;
}
#Before
public void before() {
if (failureCount > threshold) {
if (driver !=null) {
driver.quit();
driver = null;
}
}
}
Suppose I develop an extension which disallows test method names to start with an uppercase character.
public class DisallowUppercaseLetterAtBeginning implements BeforeEachCallback {
#Override
public void beforeEach(ExtensionContext context) {
char c = context.getRequiredTestMethod().getName().charAt(0);
if (Character.isUpperCase(c)) {
throw new RuntimeException("test method names should start with lowercase.");
}
}
}
Now I want to test that my extension works as expected.
#ExtendWith(DisallowUppercaseLetterAtBeginning.class)
class MyTest {
#Test
void validTest() {
}
#Test
void TestShouldNotBeCalled() {
fail("test should have failed before");
}
}
How can I write a test to verify that the attempt to execute the second method throws a RuntimeException with a specific message?
Another approach could be to use the facilities provided by the new JUnit 5 - Jupiter framework.
I put below the code which I tested with Java 1.8 on Eclipse Oxygen. The code suffers from a lack of elegance and conciseness but could hopefully serve as a basis to build a robust solution for your meta-testing use case.
Note that this is actually how JUnit 5 is tested, I refer you to the unit tests of the Jupiter engine on Github.
public final class DisallowUppercaseLetterAtBeginningTest {
#Test
void testIt() {
// Warning here: I checked the test container created below will
// execute on the same thread as used for this test. We should remain
// careful though, as the map used here is not thread-safe.
final Map<String, TestExecutionResult> events = new HashMap<>();
EngineExecutionListener listener = new EngineExecutionListener() {
#Override
public void executionFinished(TestDescriptor descriptor, TestExecutionResult result) {
if (descriptor.isTest()) {
events.put(descriptor.getDisplayName(), result);
}
// skip class and container reports
}
#Override
public void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry) {}
#Override
public void executionStarted(TestDescriptor testDescriptor) {}
#Override
public void executionSkipped(TestDescriptor testDescriptor, String reason) {}
#Override
public void dynamicTestRegistered(TestDescriptor testDescriptor) {}
};
// Build our test container and use Jupiter fluent API to launch our test. The following static imports are assumed:
//
// import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass
// import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request
JupiterTestEngine engine = new JupiterTestEngine();
LauncherDiscoveryRequest request = request().selectors(selectClass(MyTest.class)).build();
TestDescriptor td = engine.discover(request, UniqueId.forEngine(engine.getId()));
engine.execute(new ExecutionRequest(td, listener, request.getConfigurationParameters()));
// Bunch of verbose assertions, should be refactored and simplified in real code.
assertEquals(new HashSet<>(asList("validTest()", "TestShouldNotBeCalled()")), events.keySet());
assertEquals(Status.SUCCESSFUL, events.get("validTest()").getStatus());
assertEquals(Status.FAILED, events.get("TestShouldNotBeCalled()").getStatus());
Throwable t = events.get("TestShouldNotBeCalled()").getThrowable().get();
assertEquals(RuntimeException.class, t.getClass());
assertEquals("test method names should start with lowercase.", t.getMessage());
}
Though a little verbose, one advantage of this approach is it doesn't require mocking and execute the tests in the same JUnit container as will be used later for real unit tests.
With a bit of clean-up, a much more readable code is achievable. Again, JUnit-Jupiter sources can be a great source of inspiration.
If the extension throws an exception then there's not much a #Test method can do since the test runner will never reach the #Test method. In this case, I think, you have to test the extension outside of its use in the normal test flow i.e. let the extension be the SUT.
For the extension provided in your question, the test might be something like this:
#Test
public void willRejectATestMethodHavingANameStartingWithAnUpperCaseLetter() throws NoSuchMethodException {
ExtensionContext extensionContext = Mockito.mock(ExtensionContext.class);
Method method = Testable.class.getMethod("MethodNameStartingWithUpperCase");
Mockito.when(extensionContext.getRequiredTestMethod()).thenReturn(method);
DisallowUppercaseLetterAtBeginning sut = new DisallowUppercaseLetterAtBeginning();
RuntimeException actual =
assertThrows(RuntimeException.class, () -> sut.beforeEach(extensionContext));
assertThat(actual.getMessage(), is("test method names should start with lowercase."));
}
#Test
public void willAllowTestMethodHavingANameStartingWithAnLowerCaseLetter() throws NoSuchMethodException {
ExtensionContext extensionContext = Mockito.mock(ExtensionContext.class);
Method method = Testable.class.getMethod("methodNameStartingWithLowerCase");
Mockito.when(extensionContext.getRequiredTestMethod()).thenReturn(method);
DisallowUppercaseLetterAtBeginning sut = new DisallowUppercaseLetterAtBeginning();
sut.beforeEach(extensionContext);
// no exception - good enough
}
public class Testable {
public void MethodNameStartingWithUpperCase() {
}
public void methodNameStartingWithLowerCase() {
}
}
However, your question suggests that the above extension is only an example so, more generally; if your extension has a side effect (e.g. sets something in an addressable context, populates a System property etc) then your #Test method could assert that this side effect is present. For example:
public class SystemPropertyExtension implements BeforeEachCallback {
#Override
public void beforeEach(ExtensionContext context) {
System.setProperty("foo", "bar");
}
}
#ExtendWith(SystemPropertyExtension.class)
public class SystemPropertyExtensionTest {
#Test
public void willSetTheSystemProperty() {
assertThat(System.getProperty("foo"), is("bar"));
}
}
This approach has the benefit of side stepping the potentially awkward setup steps of: creating the ExtensionContext and populating it with the state required by your test but it may come at the cost of limiting the test coverage since you can really only test one outcome. And, of course, it is only feasible if the extension has a side effect which can be evaulated in a test case which uses the extension.
So, in practice, I suspect you might need a combination of these approaches; for some extensions the extension can be the SUT and for others the extension can be tested by asserting against its side effect(s).
After trying the solutions in the answers and the question linked in the comments, I ended up with a solution using the JUnit Platform Launcher.
class DisallowUppercaseLetterAtBeginningTest {
#Test
void should_succeed_if_method_name_starts_with_lower_case() {
TestExecutionSummary summary = runTestMethod(MyTest.class, "validTest");
assertThat(summary.getTestsSucceededCount()).isEqualTo(1);
}
#Test
void should_fail_if_method_name_starts_with_upper_case() {
TestExecutionSummary summary = runTestMethod(MyTest.class, "InvalidTest");
assertThat(summary.getTestsFailedCount()).isEqualTo(1);
assertThat(summary.getFailures().get(0).getException())
.isInstanceOf(RuntimeException.class)
.hasMessage("test method names should start with lowercase.");
}
private TestExecutionSummary runTestMethod(Class<?> testClass, String methodName) {
SummaryGeneratingListener listener = new SummaryGeneratingListener();
LauncherDiscoveryRequest request = request().selectors(selectMethod(testClass, methodName)).build();
LauncherFactory.create().execute(request, listener);
return listener.getSummary();
}
#ExtendWith(DisallowUppercaseLetterAtBeginning.class)
static class MyTest {
#Test
void validTest() {
}
#Test
void InvalidTest() {
fail("test should have failed before");
}
}
}
JUnit itself will not run MyTest because it is an inner class without #Nested. So there are no failing tests during the build process.
Update
JUnit itself will not run MyTest because it is an inner class without #Nested. So there are no failing tests during the build process.
This is not completly correct. JUnit itself would also run MyTest, e.g. if "Run All Tests" is started within the IDE or within a Gradle build.
The reason why MyTest was not executed is because I used Maven and I tested it with mvn test. Maven uses the Maven Surefire Plugin to execute tests. This plugin has a default configuration which excludes all nested classes like MyTest.
See also this answer about "Run tests from inner classes via Maven" and the linked issues in the comments.
JUnit 5.4 introduced the JUnit Platform Test Kit which allows you to execute a test plan and inspect the results.
To take a dependency on it from Gradle, it might look something like this:
testImplementation("org.junit.platform:junit-platform-testkit:1.4.0")
And using your example, your extension test could look something like this:
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.fail
import org.junit.platform.engine.discovery.DiscoverySelectors
import org.junit.platform.testkit.engine.EngineTestKit
import org.junit.platform.testkit.engine.EventConditions
import org.junit.platform.testkit.engine.TestExecutionResultConditions
internal class DisallowUpperCaseExtensionTest {
#Test
internal fun `succeed if starts with lower case`() {
val results = EngineTestKit
.engine("junit-jupiter")
.selectors(
DiscoverySelectors.selectMethod(ExampleTest::class.java, "validTest")
)
.execute()
results.tests().assertStatistics { stats ->
stats.finished(1)
}
}
#Test
internal fun `fail if starts with upper case`() {
val results = EngineTestKit
.engine("junit-jupiter")
.selectors(
DiscoverySelectors.selectMethod(ExampleTest::class.java, "TestShouldNotBeCalled")
)
.execute()
results.tests().assertThatEvents()
.haveExactly(
1,
EventConditions.finishedWithFailure(
TestExecutionResultConditions.instanceOf(java.lang.RuntimeException::class.java),
TestExecutionResultConditions.message("test method names should start with lowercase.")
)
)
}
#ExtendWith(DisallowUppercaseLetterAtBeginning::class)
internal class ExampleTest {
#Test
fun validTest() {
}
#Test
fun TestShouldNotBeCalled() {
fail("test should have failed before")
}
}
}