I am writing tests with Arquillian embedded. But i am facing issue when my bean is in View Scope. I just posted my sample code. When my DataBean is in ViewScope it doesn't run and throws some exception. But when i changed it to RequestScope it worked fine.
#RunWith(Arquillian.class)
public class MockTest {
#Deployment
public static Archive<?> createDeployment() {
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
.addClass("pack.ui.DataBean")
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
return jar;
}
#Inject
private DataBean dataBean;
#Test
public void testDataBean() throws Exception {
dataBean.checkSystemStatus();
Assert.assertEquals(status, true);
}
#ViewScoped
#Named("dataBean")
public class DataBean {
public boolean checkSystemStatus() {
return true;
}
}
Can someone please tell, Can we use ViewScope with Arquillian or anything else i have to do.
It's because the view scope is not active during the invocation of your test. To run it this way, you'll need to use something like drone/graphene. It's not active because the HTTP request that runs is against the arquillian test runner servlet, not the webpage of your application. ViewScope is specific to a page in your application.
You can mock JSF context of controllers and get rid of annoying exception "No active contexts for scope type ViewScoped" during Arquillian test execution.
Check the original project for JSF 2.0: https://github.com/it-crowd/mock-contexts-extension
or my upgrade for JSF 2.2: https://github.com/kesha/mock-contexts-extension
All you need is the additional annotation #ViewScopeRequired before the test method.
Related
class AbstractXYZClass{
...
#AroundInvoke
public Object intercept(InvocationContext ctx) ... {
log("do intercepting");
ctx.proceed();
}
...
}
#Stateless
class XYZClass extends AbstractXYZClass{
...
public void iWantToTestThisMethod() {...}
...
}
(running this on Server the interception for iWantToTestThisMethod() works fine)
In my unit tests (using Needle ...#ObjectUnderTest(implementation=XYZClass.class)...) #AroundInvoke doesn't get invoked
How can I JUnit-test XYZClass::iWantToTestThisMethod with intercept() intercepting?
Needle4j is a dependency injection "simulator", it does not support advanced lifecyles and scopes. So you will have to come up with a different testing strategy.
I would stick to needle4j when it comes to injection and verification of correct method interactions but switch to something like CDI-Unit or Arquillian for the actual framework-behavior tests.
Here is my abstract class which starts Jersey with given Spring context:
public abstract class AbstractJerseyTest extends JerseyTest {
public void setUp() throws Exception {
super.setUp();
}
#AfterClass
public void destroy() throws Exception {
tearDown();
}
#Override
protected URI getBaseUri() {
return URI.create("http://localhost:9993");
}
#Override
protected Application configure() {
RestApplication application = new RestApplication();
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
properties.put("contextConfigLocation", "classpath:spring-context-test.xml");
application.setProperties(properties);
application.register(this);
return application;
}
}
So, the problem is that I need to access Spring bean from my test to populate database with some data.
Jersey version is 2.6
Also I found a similar question here
But it's related to Jersey 1.x so it doesn't work for Jersey 2.x
Could anyone point me in the right direction?
Solution was really simple.
I added:
#Autowired
private Repository repository;
to the AbstractJerseyTest and this field was automatically autowired during test startup. I don't know details about how it works, but it seems that when I register instance of the test in REST application
application.register(this);
it automatically autowires all beans in the test.
Normally in your case, I'd just say work with mocks, but there are cases where you may need to expose the services in the test class.
To do this without any "ugly hacks", you will need to get a handle on the ServiceLocator (which is analogous to Spring's ApplicationContext). When the Jersey app boots up, all the Spring services from the ApplicationContext are put into the ServiceLocator through HK2's Spring bridge.
The problem is JerseyTest does not expose the ServiceLocator in any way. The only way I can think of to get a hold of it, is to create your own TestContainerFactory, and create the ApplicationHandler, which exposes the ServiceLocator.
Trying to implement your own TestContainerFactory is not a walk in the park, if you don't know what you're doing. The easiest thing to do is just look at the source code for Jersey's InMemoryTestContainerFactory. If you look at the constructor for the inner class InMemoryTestContainer, you will see it creating the ApplicationHandler. This is how you can expose the ServiceLocator, through the appHandler.getServiceLocator().
So if you copied that class, and exposed the ServiceLocator, you could create your JerseyTest extension, and call the ServiceLocator.inject(Object) method to inject the test class.
public abstract class AbstractServiceLocatorAwareJerseyTest extends JerseyTest {
private final ServiceLocatorAwareInMemoryTestContainerFactory factory
= new ServiceLocatorAwareInMemoryTestContainerFactory();
private ServiceLocator locator;
#Override
public TestContainerFactory getTestContainerFactory() {
return factory;
}
#Before
#Override
public void setUp() throws Exception {
super.setUp();
this.locator = factory.getServiceLocator();
if (injectTestClass()) {
this.locator.inject(this);
}
}
public boolean injectTestClass() {
return true;
}
public ServiceLocator getServiceLocator() {
return locator;
}
}
And if for any reason you needed it, the ServiceLocator also has the ApplicationContext, which you could also expose to your test class if needed.
I put together a GitHub project, with a complete implementation, with tests if you want to take a look at it.
UPDATE
Though the OP's answer to this question works, I believe the fact that it works, is a bug. I originally deleted this answer, after the OP posted their answer, but after some testing, I believe that solution is a bug, so I've undeleted this post for anyone who doesn't like the warning1 you get when you use that solution
1. "WARNING: A provider SimpleTest registered in SERVER runtime does not implement any provider interfaces applicable in the SERVER runtime. Due to constraint configuration problems the provider SimpleTest will be ignored."
I have a bundle-context-osgi.xml file that lists services my project takes and services it publishes. I also have a bundle-context.xml that defines the beans defined in my application. How can I write a unit test that ensures that everything is wired correctly and I can product the services that my application is supposed to provide when it is on the server?
Note: it might be wrong to call this a "unit test" but I think the idea is clear.
For OSGi Integration Tests I usually use Pax Exam. It will start a osgi container publish all configured bundles and will create a tiny-bundle from the testsources to be deployed as a OSGi bundle.
With it you are able to access all registered services even by #Inject means.
Best to take a look at the Pax Exam documentation.
In short you create a new integration test module, where you configure your dependencies in the Test case:
#RunWith(PaxExam.class)
#ExamReactorStrategy(PerMethod.class)
public class MyTest {
#Inject
protected BundleContext bundleContext;
#Inject
MyService service;
...
#Configuration
public Option[] configure() {
return options(
workingDirectory("target/paxexam/"),
cleanCaches(true),
junitBundles(),
mavenBundle().groupId("my.group.id")
.artifactId("my-artifact")
.version("1.0.0")
...
);
}
...
#Test
public void test() throws Exception {
assertNotNull(service);
}
}
I am using Arquillian and TestNG with CDI.
Before each test I need access to some members that are CDI beans to do some setup before each test. But i noticed that in every #Before annotation the CDI beans were not injected, but in the #Test annotated method they are.
Can someone explain me why:
1) CDI beans are not yet injected in the #BeforeXXX annotated methods part of the test life cyle?
2) How can I do some setup and access CDI beans before the Tests?
3) Would be correct used the "dependency" attribute in the #Test annotation?
Thank you so much.
I think I already understood the problem.
The tests run in two different places:
- in the client: maven jvm
- in the container: server jvm
In the client side, the CDI beans are not available in the #BeforeMethod, but they will when the test is running in the container. Basically if we need to access CDI beans in the before method we just need to make sure that the test is running in the container. To accomplish this i created a class that extends Arquillian and expose a method that does this.
public abstract class BaseArquillianTest extends Arquillian {
#ArquillianResource
protected InitialContext initialContext;
#Deployment
#OverProtocol("Servlet 3.0")
public static WebArchive createDeployment() {
WebArchive war = PackagingUtil.getWebArchiveForEJB();
return war;
}
protected boolean inContainer() {
// If the injection is done we're running in the container.
return (null != initialContext);
}
}
We just have to do this check in #BeforeMethod method
#BeforeMethod(alwaysRun = true)
public void beforeMethod() throws Exception {
System.out.println("********* Initing beforeMethod");
if(inContainer()) {
System.out.println("$$$$$$ I am in a container");
Assert.assertNotNull(allRiskConfigurations);
} else {
System.out.println("$$$$$$ I am NOT in a container");
}
}
In the end, the tests in the client looks like they are ignored to reflect the results of the tests that were executed in the container.
If this is wrong, can someone please correct?
Thank you all anyway. I Hope this help
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"/applicationContext-test.xml"})
#Transactional
public class MyServiceTest {
#Resource(name="myService")
public MyService myService;
#Test
public void testSeomthing() {
//do some asserts using myService.whatever()
}
}
However the tests are based on data I migrate in, so every time I run my suite of tests I want to execute my unrelated migration code. I don't want to run a #Before in each test class. I want to run it once at beginning of complete test process, where can I put this ?
I would advice you to create a test bean somewhere with startup logic invoked in #PostConstruct:
#Service
public class TestBean {
#PostConstruct
public void init() {
//startup logic here
}
}
Obviously this bean should only be created for tests, the easiest way to achieve this is to place it in src/test/java in a package that is component-scanned by Spring for #Service-annotated classes.
Note: you must remember that #PostConstruct is not running in a transaction! See How to call method on spring proxy once initialised.
JUnit also offers a #BeforeClass annotation which you can place on a static method to initialize resources just once.