I build a controller in spark java, but do not know how to test it.
The controller class:
public class PdfController {
public PdfController(final Pdf pdf) {
post("/", (req, res) -> {
InputStream stream = new ByteArrayInputStream(req.bodyAsBytes());
PdfState state = pdf.validate(stream);
res.type("application/json");
return JsonUtil.toJson(state);
});
}
}
I build the test boilerplate
public class PdfControllerTest {
#BeforeClass
public static void beforeClass() {
PdfInspector.main(null);
}
#Test(groups = {"fast"})
public void IsPdfContentRequestValid_StreamValidPdfContent_ExpectJsonSuccess() {
}
#AfterClass
public static void afterClass() {
Spark.stop();
}
}
But do not know how to write a test method.
How to write an integration test in spark java?
Download POSTMAN from chrome web store and make changes in your code so that your code could accept data... and also use "maven install" from eclipse to build your project, javaspark framework will call embedded jetty server and will run on that server...
TRY "localhost:4567/" to access your page from POSTMAN and do send some JSON or other input to that code...
Related
We defined one testng result listener which help us to send the testing result for each test case defined in testng.xml to one internal tool such like below:
public class TestResultsListener implements ITestListener, ISuiteListener {
#Override
public void onFinish(ISuite suite){
// some code to send the final suite result to internal tools
}
#Override
public void onTestSuccess(ITestResult iTestResult) {
this.sendResult(iTestResult,"PASS");Result
}
private void sendStatus(ITestResult iTestResult, String status){
// Set test case information
......
jsonArr.add(testResult);
}
}
And then we integrated this listener to other project's testng xml file such like:
<listeners>
<listener class-name="com.qa.test.listener.TestesultsListener" />
</listeners>
It worked as designed: once the test suite finishes, the test result will be uploaded to internal tools.
Now we have one requirement that in one project, one test case in testng.xml is related to 3 test cases in internal tool which means that for one test case in testng.xml we need to update 3 test cases in internal tools. How can we update our current testng listener to fulfill this?
Thanks a lot.
You can annotate each of your tests with the list of corresponding internal test tool ids:
Here I suppose that you have 2 testng tests: one is related to internal test IT-1, and the other one to internal tests IT-2, IT-3 and IT-4:
#Listeners(MyTestListener.class)
public class TestA {
#Test
#InternalTool(ids = "IT-1")
public void test1() {
System.out.println("test1");
fail();
}
#Test
#InternalTool(ids = {"IT-2", "IT-3", "IT-4"})
public void test2() {
System.out.println("test2");
}
}
The annotation is simply defined like this:
#Retention(RetentionPolicy.RUNTIME)
public #interface InternalTool {
String[] ids();
}
The your listener has just to figure out which annotation are present on successful/failed tests:
public class MyTestListener extends TestListenerAdapter implements ITestListener {
#Override
public void onTestSuccess(ITestResult tr) {
super.onTestSuccess(tr);
updateInternalTool(tr, true);
}
#Override
public void onTestFailure(ITestResult tr) {
super.onTestFailure(tr);
updateInternalTool(tr, false);
}
private void updateInternalTool(ITestResult tr, boolean success) {
InternalTool annotation = tr.getMethod().getConstructorOrMethod().getMethod().getAnnotation(InternalTool.class);
for (String id : annotation.ids()) {
System.out.println(String.format("Test with id [%s] is [%s]", id, success ? "successful" : "failed"));
}
}
}
The following output is produced:
test1
Test with id [IT-1] is [failed]
test2
Test with id [IT-2] is [successful]
Test with id [IT-3] is [successful]
Test with id [IT-4] is [successful]
You can also extend this mechanism to Suite listeners as well.
Disclaimer: The line
InternalTool annotation = tr.getMethod().getConstructorOrMethod().getMethod().getAnnotation(InternalTool.class); is not bullet-proof (high risk of null pointer exception). Should be more robust.
I am using Play Framework and using Java as the language of choice. I have a Controller which makes a REST call to an external service. I intend to mock the external service, so that I can test the functionality of my controller. To achieve this, I have created my test cases as shown below (sample). I am embedding a server within my test to mock the external service.
public class SomeControllerTest extends WithApplication {
private static Server SERVER;
#Override
protected Application provideApplication() {
final Module testModule = new AbstractModule() {
#Override
public void configure() {
bind(AppDao.class).to(MockAppDaoImpl.class);
}
};
return new GuiceApplicationBuilder().in(Environment.simple()).overrides(testModule).build();
}
#BeforeClass
public static void setup() {
Router router = new RoutingDsl()
.POST("/api/users")
.routeTo(() -> created())
.build();
SERVER = Server.forRouter(router, 33373);
PORT = SERVER.httpPort();
}
#AfterClass
public static void tearDown() {
SERVER.stop();
}
#Test
public void testCreateUser() {
ObjectNode obj = Json.newObject();
obj.put("name", "John Doe");
obj.put("email", "john.doe#example.com");
Http.RequestBuilder request = new Http.RequestBuilder()
.method(POST)
.bodyJson(obj)
.uri("/some/url/here");
Result result = route(request);
assertEquals(ERR_MSG_STATUS_CODE, CREATED, result.status());
assertEquals(ERR_MSG_CONTENT_TYPE, Http.MimeTypes.JSON, result.contentType().get());
}
My expectation is that when I run the test, the mock server would run and based on my application's test configuration, my controller will make a call to the mock server which would return 201 and my test case would pass.
But, this doesn't happen, because as soon as setup() method completes, the mock server is killed, and my controller cannot make a call to it.
What am I doing wrong here?
Testing of controller should be rather done by inheritance from WithApplication
public class TestController extends WithApplication {
#Test
public void testSomething() {
Helpers.running(Helpers.fakeApplication(), () -> {
// put test stuff
// put asserts
});
}
}
In order to test a controller method use Helpers.fakeRequest and reverse routing.
The external service may be just mocked with mockito or other mocking framework you like.
You can find here several examples.
I am currently writing tests for some REST-full Services I wrote. The services I am testing are written in Java and use MongoDb/Morphia. The tests call on the services, some of which in turn write to a test collection. I need to clean up after the tests and delete the data I injected. What is the best way to go about this?
Here is an example of one of my simple services:
package org.haib.myerslab.services;
#Path("/database")
public class DatabaseService {
#Inject
private Datastore ds;
#Path("/genre/")
#POST
#Produces("application/json")
public GenreDTO postFromGenreDTO(#Context UriInfo uri, GenreDTO form) throws ParseException {
Genre myNewGenre = DtoToDomainMapper.gerneFromGenreDTO(form);
myNewGenre.setId(form.getId());
ds.save(myNewGenre);
return new GenreDTO(myNewGenre);
}
}
And here is an example of my Arquillian test:
#RunWith(Arquillian.class)
public class GeneTest {
private static String myId = "myGenreId";
private static String myGenre = "myGenre";
private static String myGenreInfo = "myGenreInfo";
#Deployment
public static WebArchive getDeployment() {
return TestHelper.getDeployment();
}
#Test
#RunAsClient
#InSequence(1)
public void canPostGenre(#ArquillianResource URL baseURL) throws Exception {
GenreDTO newGenre = new GenreDTO();
newGenre.setGenre(myGenre);
newGenre.setGenreInfo(myGenreInfo);
newGenre.setId(myId);
String url = baseURL.toURI().resolve("/database/genre/").toString();
JsonNode rootNode = TestHelper.postUrl(url, newGene);
assertEquals(myGenre, rootNode.get("genre").asText());
assertEquals(myGenreInfo, rootNode.get("genreInfo").asText());
assertEquals(myId, rootNode.get("id").asText());
}
}
Where the getDeployment function looks like this:
public static WebArchive getDeployment() {
File[] depend = Maven.resolver().loadPomFromFile("pom.xml").importRuntimeDependencies().resolve().withTransitivity().asFile();
WebArchive war = ShrinkWrap.create(WebArchive.class).addClass(TestHelper.class)
.addClass(Genre.class).addClass(Application.class).addPackage("org/haib/myerslab")
.addPackage("org/haib/myerslab/database").addPackage("org/haib/myerslab/genre")
.addPackage("org/haib/myerslab/dto").addPackage("org/haib/myerslab/dto/genre")
.addAsLibraries(depend).addAsWebInfResource("jboss-deployment-structure.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml").setWebXML("test-web.xml");
return war;
}
So where I am lost is, what is the best way to Inject the database in an #After, and clear our the Genre Class I posted into it so that my next test doesn't have it there.
How should I do this? Is there another way?
Take a look at nosql-unit. It provides annotations and rules that help you with seeding datasets, comparing expectations and cleaning up MongoDB.
To get your MongoDB into a pristine state before executing a test, you can simply use the following Annotation with the `CLEAN_INSERT´ :
#UsingDataSet(locations="my_data_set.json", loadStrategy=LoadStrategyEnum.CLEAN_INSERT)
public void canPostGenre() { ...}
If you need the behavior around the integration testing lifecycle with MongoDB to be more powerful, you can also roll your own based on the ideas of nosql-unit. Also make sure to check out Junit Rules.
I set up WS server using this tutorial http://java.dzone.com/articles/jax-ws-hello-world (that Java client works correctly, of course) and trying to call the client in Grails project like this:
Client.java
public class Client {
public static void main(String[] args) {
GreetingImplService service = new GreetingImplService();
Greeting greeting = service.getGreetingImplPort();
System.out.println("------->> Call Started");
System.out.println(greeting.sayHello("Ali"));
System.out.println("------->> Call Ended");
}
}
TestController.groovy
class TestController {
def index() {
Client.main(null);
}
}
In case of Grails, exception is thrown on this command:
Greeting greeting = service.getGreetingImplPort();
full stacktrace is here http://pastebin.ca/2316018
how to fix it?
Install the WSClient plugin for Grails, then write:
def proxy = webService.getClient(wsdlURL)
def result = proxy.getGreetingImplPort()
We're transitioning from using TestNG with an embedded JBoss to using Arquillian with a remote server.
We are running a simple test that has a method annotated with #BeforeClass that does some test setup. After a lot of digging, it looks like that setup method is being called twice: once on the console where we're executing our Maven command to run the test and again when the test war is deployed to our remote server and the test runs. These are two separate JVMS - one running outside the container and another running inside the container. My preference is to just have the latter run.
Is this the behavior I should expect or is there something I may be missing?
For now, we're actually checking to see if we're in the container or not and, if so, we run our setup code. This works but I'd like to know if there's a better way.
Some snippets of our code (please ignore the simplicity of the code and the fact that the setupComponents method really isn't needed here, there are much more complicated tests that we're migrating that will need this functionality):
public class BaseTest extends Arquillian
{
private static Log log = LogFactory.getLog( SeamTest.class );
#Deployment
public static Archive<?> createDeployment()
{
// snip... basically, we create a test war here
}
/**
* todo - there might be a better way to do this
*/
private boolean runningInContainer()
{
try
{
new InitialContext( ).lookup( "java:comp/env" );
return true;
}
catch (NamingException ex)
{
return false;
}
}
#BeforeClass
public void setupOnce() throws Exception
{
getLog().debug( "in setupOnce(): " + runningInContainer() );
if ( runningInContainer() )
{
new ComponentTest()
{
protected void testComponents() throws Exception
{
setupComponents();
}
}.run();
}
}
public User createUser()
{
// ...
}
public Log getLog()
{
// snip...
}
public UserDao getUserDao()
{
// ...
}
public abstract class ComponentTest
{
protected abstract void testComponents() throws Exception;
public void run() throws Exception
{
try {
testComponents();
} finally {
}
}
}
}
public class UserDaoTest extends BaseTest
{
UserDao userDao;
#Override
protected void setupComponents()
{
getLog().debug( "in setupComponents: " + runningInContainer() );
userDao = getUserDao();
}
#Test
public void testGetUser() throws Exception
{
getLog().debug( "in testGetUser: " + runningInContainer() );
new ComponentTest()
{
protected void testComponents() throws Exception
{
User user0 = createUser();
user0.setName( "frank" );
userDao.merge( user0 );
User retrievedUser = userDao.findByName( "frank" );
assertNotNull( retrievedUser );
}
}.run();
}
}
This basically gives me output that looks like this:
From the console where mvn is being executed:
in setupOnce(): false
From the jboss server:
in setupOnce(): true
in setupComponents: true
in testGetUser: true
This is "expected" behaviour. Not really nice, but it is how Arqullian works.
JUnit
#BeforeClass / #AfterClass are only executed on ClientSide
The state of the test class is lost between #Test, in container the whole lifecycle is repeated for each test
#Before / #After are executed depending on the runmode (client/server)
TestNG
everything is run both on server and client