I have a spring-based groovy application that is used as a "framework" for running TestNG tests.
Here is a part of my application
#RestController
class Framework{
def instance
#RequestMapping("/test/{name}")
#ResponseBody
String home(#PathVariable String name) {
def sourceFile = new File("./tests/${name}/test.groovy")
groovyClass = new GroovyClassLoader(getClass().getClassLoader()).parseClass(sourceFile)
instance = groovyClass.newInstance()
def testNG = new TestNG()
testNG.setOutputDirectory("./results/${name}")
XmlSuite suite = new XmlSuite()
suite.setName(name)
XmlTest test = new XmlTest(suite)
test.setXmlClasses([new XmlClass(groovyClass)])
testNG.setXmlSuites([suite])
testNG.run()
def resultFile = new File("./results/${name}/emailable-report.html")
return resultFile.text
}
#RequestMapping("/status")
public String getStatus(){
return instance.currentMethod
}
}
My example test file looks like
class T1{
public String currentMethod
#Test
public void test() {
//execution
}
#Test
public void test2(){
//execution
throw new Exception()
}
}
It works fine as it is but I wanted to implement some additional information to be able to check which method is currently running by adding some more code
#BeforeMethod
void setMethodName(){
String className = this.class.getName()
def classData = Thread.currentThread().getStackTrace().toList().reverse().find{ it =~ /${className}/}
currentMethod = classData.getMethodName()
}
However I am not able to access the instance as
instance = groovyClass.newInstance()
creates one instance and
testNG.run()
creates another which can be confirmed by printing some mesages in construcor.
ctor
ctor
[TestNG] Running:
Command line suite
===============================================
Total tests run: 2, Failures: 1, Skips: 0
===============================================
Any idea how can I access istance created by TestNG or how to pass existing instance into TestNG runner?
Each time i try to access localhost:8080/status it returns null.
ITestListener is what you are looking for. Check its documentation.
You'll be able to add the listener with:
testNG.addListener(....);
And we can imagine your listener will have:
listener.getCurrentMethod();
And fyi, it is possible to inject a Method instance into a #BeforeMethod method.
Related
I have a method in OneServiceImpl class as follows. In that class I am calling an interface method from another class.
public class OneServiceImpl {
//created dependency
final private SecondService secondService;
public void sendMessage(){
secondService.validateAndSend(5)
}
}
public interface SecondService() {
public Status validateAndSend(int length);
}
public class SecondServiceImpl {
#Override
public Status ValidateAndSend(int length) {
if(length < 5) {
throw new BadRequestException("error", "error");
}
}
}
Now when I am try to perform unit test on OneServiceImpl I am not able to throw a BadRequestException.
when(secondService.validateAndSend(6)).thenThrow(BadRequestException.class);
Not quite sure what your use case is, but I think you should write an own test to accept and test an exception.
#Test(expected = BadRequestException.class)
public void testValidateAndSend(){
SecondService secondService = new SecondService();
secondservice.ValidateAndSend(6); //method should be lowercase
}
Not sure this is the case considering you didn't post a full example of code + unit tests, but your mock will throw only when you are passing 6 as parameter. When configuring the behaviour of your mock with when you are telling it to throw only when the validateAndSend method is called with parameter 6.
when(secondService.validateAndSend(6)).thenThrow(...)
In your code you have 5 hardcoded. So that mock will never throw for the code you have, because it's configured to react to an invocation with parameter 6 but the actual code is always invoking it passing 5.
public void sendMessage(){
secondService.validateAndSend(5)
}
If the value passed to the mock is not important you could do something like the following, that will throw no matter what's passed to it:
when(secondService.validateAndSend(any())).thenThrow(BadRequestException.class);
On the other hand, if the value is important and it has to be 5 you could change the configuration of your mock with:
when(secondService.validateAndSend(5)).thenThrow(BadRequestException.class)
I set this testing scenario with citrus framework. Now I'm trying to reuse it in other scenarios.
I'm creating a behavior for each step. My behaviors are mainly http requests
public class NoProductDocumentValidationScenarioIT {
private #CitrusResource TestContext parentContext;
#CitrusEndpoint(name = "todoBasicAuthClient")
private HttpClient cmsAuthClient;
#CitrusEndpoint(name = "vdmBasicAuthClient")
private HttpClient vdmAuthClient;
#CitrusEndpoint(name = "gvHttpClient")
private HttpClient gvHttpClient;
#Test
#CitrusTest
public String NoProductDocumentValidation(#CitrusResource TestRunner runner, #CitrusResource TestContext context)
throws BadNewsMLG2Exception {
String pdtIdentifier = "EDIT-FR-SVID2-YM9N001479";
String videoDocument = VideoDocument.setUpVideoDocument("fr", "v1_afptv_sport_broadcast_photos");
int jobPublicationID = 5;
// CMS Authentification
TestBehavior authenticateCMS = new ProductAuthenticationBehavior(cmsAuthClient);
ApplyTestBehaviorAction authenticateActionCMS = new ApplyTestBehaviorAction(runner, authenticateCMS);
authenticateActionCMS.doExecute(context);
// Document Creation
CreateVideoDocumentBehavior createDoc = new CreateVideoDocumentBehavior(cmsAuthClient, pdtIdentifier,
videoDocument);
ApplyTestBehaviorAction createDocAction = new ApplyTestBehaviorAction(runner, createDoc);
createDocAction.doExecute(context);
// get document data
videoDocument = createDoc.getVideoDocument();
G2VideoDocument g2VideoDocument = ((G2VideoDocument) G2ObjectFactory.parse(videoDocument));
g2VideoDocument.getProducts();
String linkToVideoDocument = g2VideoDocument.getLinkToSelf().toString();
String linkToProject = g2VideoDocument.getLinkToVideoProject().toString();
String projectID = IrisStringTools.extractIdFromUri(linkToProject);
String documentID = IrisStringTools.extractIdFromUri(linkToVideoDocument);
String etag = g2VideoDocument.getEditorialTag();
// Lock document Metadata
EditVideoDocumentMetaBehavior lockDocMeta = new EditVideoDocumentMetaBehavior(cmsAuthClient, pdtIdentifier,
videoDocument, documentID);
ApplyTestBehaviorAction lockDocMetaAction = new ApplyTestBehaviorAction(runner, lockDocMeta);
lockDocMetaAction.doExecute(context);
}
}
I run this in eclipse as JUnit test.
I thought about using a super class but it didn't work.
public class ProductDocumentValidationScenarioIT extends NoProductDocumentValidationScenarioIT {
public String ProductDocumentValidation(#CitrusResource TestRunner runner, #CitrusResource TestContext context)
throws BadNewsMLG2Exception {
return something;
}
}
Test behaviors is the way to go here. I suggest to use something like this
CreateVideoDocumentBehavior createDoc = new CreateVideoDocumentBehavior(cmsAuthClient, pdtIdentifier,
videoDocument);
runner.applyBehavior(createDoc);
what we finally did is to create a behavior runner (a java class) where all the behaviors are instanciated and then in the scenario we call the behavior runner with the behavior constant corresponding to the behavior I need:
public class BehaviorRunner {
private void doExecute(TestRunner runner, TestContext context, TestBehavior testBehavior) {
ApplyTestBehaviorAction behaviorAction = new ApplyTestBehaviorAction(runner,testBehavior);
behaviorAction.doExecute(context);
}
public void execute( String behaviorLabel, #CitrusResource TestRunner runner, #CitrusResource TestContext context) {
try {
switch (behaviorLabel) {
case BehaviorConstants.CREATE_VIDEO_DOCUMENT :
CreateVideoDocumentBehavior createVideoDocumentBehavior = new CreateVideoDocumentBehavior(cmsAuthClient, pdtIdentifier, VideoDocument.setUpVideoDocument2(LanguageConstants.EN, "v1_afptv_sport_broadcast_photos"));
doExecute(runner, context, createVideoDocumentBehavior);
break;
case BehaviorConstants.MOVIEDRAFT :
MovieDraftDocumentBehavior movieDraftDocumentBehavior = new MovieDraftDocumentBehavior(cmsAuthClient, pdtIdentifier, 1, g2VideoDoc);
doExecute(runner, context, movieDraftDocumentBehavior);
break;
case BehaviorConstants.PUBLICATION_PROGRESSION_STATUS:
GetPublicationProgressionStatusBehavior publicationProgressionStatusBehavior = new GetPublicationProgressionStatusBehavior(vdmAuthClient, pdtIdentifier , g2VideoDoc);
doExecute(runner, context, publicationProgressionStatusBehavior);
break;
case BehaviorConstants.VALIDATE :
ValidateDocumentBehavior validateDocumentBehavior = new ValidateDocumentBehavior(cmsAuthClient, pdtIdentifier, g2VideoDoc);
doExecute(runner, context, validateDocumentBehavior);
break;
default:
break;
}
we ended up with a scenario like this:
#Test
#CitrusTest
public void NoProductDocumentValidation(#CitrusResource TestRunner runner, #CitrusResource TestContext context) throws BadNewsMLG2Exception {
slf4jLogger.info("Montage analysis scenario START");
// execute scenario
// Document Creation
behaviorRunner.execute(BehaviorConstants.CREATE_VIDEO_DOCUMENT, runner, context);
// Lock document Metadata
behaviorRunner.execute(BehaviorConstants.EDITOR, runner, context);
// Lock Document Binary
behaviorRunner.execute(BehaviorConstants.BINARY_EDITOR, runner, context);
That saved us a lot of code lines since we're using different combinations of behaviors in different scenarios.
I hope this would help someone!
I've been looking on internet but haven't found the solution if any (new on UnitTest and Mockito)
It's possible to test a method that return a call of a service and manipulate it's result before to return it? Example;
public Observable<Reports> getUserReports(Integer userId) {
return serviceClient
.getReports(userId)
.flatMap(serviceReports -> {
System.out.println("Testing inside flatMap"); <- never reach this line therefore duno if methods down here are invoked and work perfectly
final Observable<List<Report>> reports = getPendingReports(userId, serviceReports);
//More methods that modify/update information
return zip(observable1, observable2, observable3
(report1, report2, report3) -> {
updateReports(otherArguments, report1, report2, report3);
return serviceReports;
});
});
}
So far I've tried;
#Test
public void myTest(){
when(serviceClient
.getReports(anyInt()))
.thenReturn(Observable.just(reports));
Observable<Reports> result = mocketClass.getUserReports(userId)
}
Tryed with Spy and Mock but no luck so far. Any hint or help would be great.
To mock getReports() behavior you need to mock the serviceClient firstly and pass it into your service class.
Just as example:
#Test
public void myTest(){
// Given
final ServiceClient mockedServiceClient = Mockito.mock(ServiceClient.class);
when(mockedServiceClient
.getReports(anyInt()))
.thenReturn(Observable.just(reports));
// and create an instance of your class under testing with injected mocked service client.
final MyUserService userService = new MyUserService();
userService.setServiceClient(mockedServiceClient);
// When run a method under test
Observable<Reports> actualResult = userService.getUserReports(userId)
// Then
// actualResult to be verified.
}
I am trying to test spring rest documentation for rest API for our services using spring cucumber jvm but end up with a null pointer exeception when I try to execute the scenario, as the framework is not able to intialize the Junit context.
Error Message:
java.lang.NullPointerException at
org.springframework.restdocs.ManualRestDocumentation.beforeOperation(ManualRestDocumentation.java:90) at
org.springframework.restdocs.JUnitRestDocumentation.beforeOperation(JUnitRestDocumentation.java:76)
Code:
private AppProperties props;
#Before("#rest") public void beforeScenario() {
JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation( "target/generated-snippets" );
System.out.println( "jUnitRestDocumentation " +restDocumentation );
spec = new RequestSpecBuilder().addFilter( documentationConfiguration( restDocumentation ) ).build();
System.out.println( "\n spec init .. " +restDocumentation );
}
Step definition code:
#Given("^create a rest document for VHR API$")
public void create_a_rest_document_for_VHR_API() throws Throwable {
estAssured.given( spec )
.accept( "application/json" )
.filter( document( "vhrdocument" ) ) .when()
.get( props.getVhrrequesturl() + "/vhrData/{vehicleID}", "5VW4T7AU0FM029999" ) .then().log().all();
}
You aren't using JUnitRestDocumentation as it's intended to be used. It's designed to be used as a JUnit rule which means it should be a public field annotated with #Rule:
#Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
Being a rule means that JUnit will automatically call restDocumentation for each test, allowing Spring REST Docs to set up and tear down the test-specific context. The NullPointerException is occurring because restDocumentation hasn't been called in this way and, therefore, the context hasn't been set up.
You haven't described how you're using Cucumber, but if you're using it's JUnit runner you should be able to fix the problem by declaring restDocumentation as a #Rule-annotated field as shown above. If you're not using its JUnit runner, you may need to use Spring REST Docs' ManualRestDocumentation instead. The Spring REST Docs reference documentation contains a section that describes how to set up your tests when you're not using JUnit.
I had the same problem because I had multiple test class inheriting the class, in which I declared the JUnitRestDocumentation instance. My mistake was that I declared the rule using the #Rule annotation. I should have used #ClassRule and declared the instance as static.
#ClassRule
public static JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
it happened with test SpockFramework, and i added to pom.xml:
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-junit4</artifactId>
<scope>test</scope>
</dependency>
I had the same symptoms when migrating from RestAssured 2.x to RestAssured 3.1.1.
The codebase had a way to setup RestAssured in order to avoid repetitive ceremony for every tests :
#Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
#Before
public void configure_rest_assured() {
RestAssured.port = springServerPort;
RestAssured.config = config().objectMapperConfig(
objectMapperConfig().jackson2ObjectMapperFactory((cls, charset) -> customObjectMapper)
)
...;
RestAssured.requestSpecification = new RequestSpecBuilder()
.addRequestSpecification(documentationConfiguration(docRule, ...))
...
.build();
}
This was working well, until I migrated to 3.x. The issue was that new RequestSpecBuilder() will append itself to the default static RestAssured.requestSpecification.
The first test passed, but when it finished the rule was disposed (the after part), when the second test started to ran, the Before method was chaining
the specification created for the first test (referencing the disposed rule used by the first test method)
the specification created for the second test (referencing the active rule for second test method)
And so on as new tests are ran.
But when the second test is run RestAssured invoke specification in order, e.g. the number 1, but since it was referencing a disposed rule (the beforeOperation was executed on a null context)
To fix that the code had to clear the previous specifications :
#Before
public void configure_rest_assured() {
RestAssured.port = springServerPort;
RestAssured.config = config().objectMapperConfig(
objectMapperConfig().jackson2ObjectMapperFactory((cls, charset) -> customObjectMapper)
)
...;
RestAssured.requestSpecification = null; // avoid the builder to acquire previous specs.
RestAssured.requestSpecification = new RequestSpecBuilder()
.addRequestSpecification(documentationConfiguration(docRule, ...))
...
.build();
}
For using cucumber-java-8 with spring rest docs and spring-security the following worked for me.
This is combining #AndyWilkison's answer from above but using the cucumber hooks instead of junit rules.
public class StepDefs implements En {
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
private ManualRestDocumentation restDocumentation = new ManualRestDocumentation();
public StepDefs() {
BeforeStep((Scenario scenario) -> {
restDocumentation.beforeTest(AuthenticationStepDefs.class, scenario.getName());
mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).apply(documentationConfiguration(restDocumentation)).build();
});
AfterStep((Scenario scenario) -> {
restDocumentation.afterTest();
});
When("create a rest document for VHR API", () -> {
MvcResult result = mockMvc.perform(/*
your normal call here
*/).
.andDo(document("documentation")).
.andReturn();
}
}
}
I am trying to test a custom Gradle plugin that is configured via an Extension object that would normally be present in the build.gradle file.
For example, my build.gradle would normally look something like this:
{
apply plugin: 'foobarConfigurator'
[... stuff ...]
foobarConfig {
bar = 'boop'
baz = 'baap'
bot = 'faab'
}
[... stuff ...]
}
In my custom plugin class I have code that does this in the apply method:
def config = project.extensions.create('foobarConfig', FooBarConfig)
It's unclear to me how in a JUnit test I should write my test methods so that I can provide and test for different configuration values in a foobarConfiguration in a Project instance created by the ProjectBuilder class.
Any help appreciated, thanks!
If you intend to write a JUnit test for your extension, you can simply create an instance and configure it programmatically:
class FooBarConfigTest {
private FooBarConfig fooBarConfig
#Before
public void before() {
fooBarConfig = new FooBarConfig()
}
#Test
public void example() {
fooBarConfig.bar = 'boop'
assertEquals("expectedIfBarIsBoop", fooBarConfig.someMethod())
}
}
On the other hand, to test the plugin itself, you can use a ProjectBuilder and find the extension by type:
class MyPluginTest {
private MyPlugin plugin
private Project project
#Before
public void before() {
project = ProjectBuilder.builder().build();
plugin = new MyPlugin()
plugin.apply(project)
}
#Test
public void example() {
FooBarConfig foobarConfig = project.extensions.findByType(FooBarConfig)
assertNotNull(foobarConfig)
foobarConfig.bar = 'boop'
}
}