Spock Stepwise - Keep running testsuite after single failure - spring

When using the Spock #Stepwise annotation, is there any way to configure it to not fail the entire testsuite after a single test fails?

Decided to just create a new extension called #StepThrough. All I needed to do was subclass StepwiseExtension and take out the line of code that was failing the entire test suite. Pasted code below...
StepThrough.groovy
package com.test.SpockExtensions
import org.spockframework.runtime.extension.ExtensionAnnotation
import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target
/**
* Created by jchertkov on 6/22/15.
*/
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#ExtensionAnnotation(StepThroughExtension.class)
public #interface StepThrough {}
StepThroughExtension.groovy
package com.test.SpockExtensions
import org.spockframework.runtime.extension.builtin.StepwiseExtension
import org.spockframework.runtime.model.SpecInfo
import java.lang.annotation.Annotation
/**
* Created by jchertkov on 6/22/15.
*/
public class StepThroughExtension extends StepwiseExtension {
public void visitSpecAnnotation(Annotation annotation, final SpecInfo spec) {
sortFeaturesInDeclarationOrder(spec);
includeFeaturesBeforeLastIncludedFeature(spec);
}
}
Notes:
I put the code into a package called com.test.SpockExtensions. You will need to do the same with whatever name you would like.
Java users - just change filetype from .groovy to .java

Related

Customize pointcut expression for 'declare #method'

Use case
I'd like to add programmatically an externally provided annotation named: #Trace
to all public methods in the spring-boot project
that are in a class annotated with #Controller
only within a particular package (com.example.apectitddemo.controller)
only if the method doesn't have a different custom annotation already applied, f.e. #Disable
Thanks to the above criteria, each newly added method to the project that meets them all will be #Trace annotated dynamically without any additional developer action, which is the main goal here.
My approach
I used Aspectj's ITD (inter type declaration) for this but it fulfills only 1st requirement and have no idea how to customize it for 2nd, 3rd and 4th.
Tried several ways commented out in the below code snipped.
TracingAspect.aj:
package com.example.apectitddemo.aspect;
public aspect TracingAspect {
declare #method : public * *(..) : #Trace;
//[INFO] 'public void com.example.apectitddemo.controller.ControllerPing.ping()' (ControllerPing.java) is annotated with #Trace method annotation from 'com.example.apectitddemo.aspect.TracingAspect' (TracingAspect.aj)
// declare #method : public * ((#Controller *)).*(..) : #Trace;
// declare #method : public * ((#Controller *)).*(..) && !#Disabled : #Trace;
// declare #method : public com.example.apectitddemo.controller.* :#Trace;
// declare #method : public * com.example.apectitddemo.controller+ : #Trace;
// declare #method : public * *(com.example.apectitddemo.controller.*) : #Trace;
// declare #method : public * controller..* : #Trace;
// declare #method : public * *(..) : #Trace;
}
BTW is it possible to use pure java here (TracingAspect.java) and not as .aj file?
ControllerPing.java (sample method which should be annotated by an aspect)
package com.example.apectitddemo.controller
#Controller
public class ControllerPing {
//#Trace annotation should be added here by ITD
public void ping() {
log.info("ok");
}
#Disable
public void pingDisabled() {
log.info("ok");
}
}
Misc
I was searching the internet but haven't found much documentation and even couldn't encounter any other code samples except below. The above solution is based on this finding:
how to write an aspectj itd to add an annotation to a method?
Other pages found, related:
https://www.eclipse.org/aspectj/doc/released/adk15notebook/ataspectj-itds.html
http://kto.web.elte.hu/hu/oktatas/aop_en.pdf
samples are empty :/ https://www.eclipse.org/aspectj/doc/released/examples/
Maybe there is another better way to complete the requirements?
This is a native AspectJ example. You can run it completely without Spring or from within a Spring application - up to you:
Annotations:
package de.scrum_master.stackoverflow.q73270343;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Retention(RUNTIME)
#Target({ METHOD })
public #interface Trace {}
package de.scrum_master.stackoverflow.q73270343;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Retention(RUNTIME)
#Target({ METHOD })
public #interface Disable {}
Non-controller class (negative test):
package de.scrum_master.stackoverflow.q73270343;
public class NoControllerPing {
// #Trace annotation should NOT be added here by ITD
public void ping() {
System.out.println("No controller ping");
}
#Disable
public void pingDisabled() {
System.out.println("No controller pingDisabled");
}
}
Controller class and driver application:
package de.scrum_master.stackoverflow.q73270343;
import org.springframework.stereotype.Controller;
#Controller
public class ControllerPing {
// #Trace annotation should be added here by ITD
public void ping() {
System.out.println("Controller ping");
}
#Disable
public void pingDisabled() {
System.out.println("Controller pingDisabled");
}
public static void main(String[] args) {
new ControllerPing().ping();
new ControllerPing().pingDisabled();
new NoControllerPing().ping();
new NoControllerPing().pingDisabled();
}
}
Native syntax AspectJ aspect:
package de.scrum_master.stackoverflow.q73270343;
public aspect TracingAspect {
declare #method : !#Disable public !static * (#org.springframework.stereotype.Controller *..*).*(..) : #Trace;
before() : #annotation(Trace) && execution(* *(..)) {
System.out.println(thisJoinPoint);
}
}
Console log:
execution(void de.scrum_master.stackoverflow.q73270343.ControllerPing.ping())
Controller ping
Controller pingDisabled
No controller ping
No controller pingDisabled
See AspectJ manual.
BTW is it possible to use pure java here (TracingAspect.java) and not as .aj file?
No, it is not. Quote from the AspectJ manual:
Inter-type declarations are challenging to support using an annotation style. For code style aspects compiled with the ajc compiler, the entire type system can be made aware of inter-type declarations (new supertypes, new methods, new fields) and the completeness and correctness of it can be guaranteed. Achieving this with an annotation style is hard because the source code may simply be compiled with javac where the type system cannot be influenced and what is compiled must be 'pure java'.
You only have #DeclareParents, #DeclareMixin, #DeclarePrecedence, #DeclareWarning, #DeclareError at your disposal. See also the AspectJ 5 quick reference, page 4.

Warning about config property after migrated to Quarkus 2.8.0

I have migrated an extension from quarkus 2.7.5 to quarkus 2.8.0.
After the migration, I run mvn clean install and the console shows me weird warnings about all (maybe 100) config properties (some of them are defined by me, other not like java.specification.version):
[WARNING] [io.quarkus.config] Unrecognized configuration key "my.property" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo
I think my integration-tests module causes this issue.
Here is my class in runtime folder:
import java.util.Optional;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
#ConfigRoot(phase = ConfigPhase.RUN_TIME, prefix="", name = "myApp")
public class MyAppConfig {
#ConfigItem(defaultValue = "defaultValue")
String firstProperty;
#ConfigItem(defaultValue = "")
Optional<String> secondProperty;
#ConfigItem(defaultValue = "defaultValue")
String thirdProperty;
// Getters ...
}
Here is my test:
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
#QuarkusTest
public class MyAppIntegrationTest {
#ConfigProperty(name="myApp.first-property")
String firstProperty;
#ConfigProperty(name="myApp.second-property")
String secondProperty;
#ConfigProperty(name="myApp.third-property")
String thirdProperty;
#Test
public void testConfig() {
assertEquals("firstValue", firstProperty);
assertEquals("secondValue", secondProperty);
assertEquals("thirdValue", thirdProperty);
}
}
Can someone help me on this ? For instance, do I need a BuildItem for that ?
Thanks for your help
After spending hours on those warnings, I found that they was caused by the empty prefix field of the ConfigRoot annotation.
Setting name field to "" and prefix to "myApp" fixed the issue

How do I reset #Repository after every test in SpringBootTest?

I'm trying to put together integration test for my newly created #Repository class, however not having any luck with running all tests together. If I run each test separately - they pass, however if I run the whole test class - two tests fail that attempt to find one row by id in H2 (separate db for testing) and find none.
This is my test class below:
package com.vaidas.development.gradecalculatorbackend.repositories;
import com.vaidas.development.gradecalculatorbackend.models.Module;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import static org.junit.Assert.assertEquals;
#RunWith(SpringRunner.class)
#SpringBootTest
#DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class ModuleRepositoryTest {
#Autowired
private ModuleRepository moduleRepository;
#Test
#Transactional
public void shouldInsertAndFindAll() {
// GIVEN
Module module = new Module("Test module", null);
int count = moduleRepository.findAll().size();
// WHEN
moduleRepository.insertModule(module);
int countAfter = moduleRepository.findAll().size();
// THEN
assertEquals(count,countAfter - 1);
}
#Test
#Transactional
public void shouldInsertAndFindOne() {
// GIVEN
Module module = new Module("Test module", null);
module = moduleRepository.insertModule(module);
// WHEN
Module storedModule = moduleRepository.findOne(module.getId());
// THEN
assertEquals(storedModule.toString(), module.toString());
}
#Test
#Transactional
public void shouldUpdate() {
// GIVEN
Module module = new Module("Test module", null);
module = moduleRepository.insertModule(module);
Module updatedModule = new Module("Test module updated", null);
updatedModule.setId(module.getId());
// WHEN
moduleRepository.updateModule(updatedModule);
// THEN
Module foundModule = moduleRepository.findOne(updatedModule.getId());
assertEquals(foundModule.getName(), updatedModule.getName());
}
#Test
#Transactional
public void shouldDelete() {
// GIVEN
Module module = new Module("Test module", null);
module = moduleRepository.insertModule(module);
// WHEN
moduleRepository.deleteModule(module);
// THEN
assertEquals(0, moduleRepository.findAll().size());
}
}
What I've tried:
using #DirtiesContext and #Transactional annotations which I expected to reset the DB content
using #Before and #After annotations for every test, however it seemed like they acted asynchronously and didn't wait for DB to finish adding/removing instances
The failing tests are:
shouldInsertAndFindOne() {
shouldUpdate() {
Each of the above throw the following error:
org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
Can someone explain why this would happen and what's the correct way to reset my H2 testing db before each test?
I don't know if this is the correct approach, but I usually just add a repositoryName.deleteAll() in a #Before-annotated method.
#Before
public void before() {
moduleRepository.deleteAll();
moduleRepository.flush();
}
This method will be ran before each of your #Test-annotated methods and will ensure that the moduleRepository is empty.
Also, that #Transactional annotation might be the source of your problem. Have you tried the #Before approach without that annotation? Or how about adding a #Transactional at the class level?

How to use flutter_test_config.dart

I'm trying to figure out how to use a flutter_test_config.dart file to configure a group of tests. Here is the code that I have in the file.
import 'dart:async';
import 'package:sqflite/sqflite.dart';
import 'package:mockito/mockito.dart';
class MockDatabase extends Mock implements Database {}
Future<void> main(FutureOr<void> testMain()) {
final Database db = MockDatabase();
testMain();
}
I would like to provide the db to the tests in this directory. What is the correct way to do this?

Geoserver source code: Where do the methods in classProperties.java come from

I try to understand the geoserver source code and therefore play around with it. For my task I want to find out where I can find the "methods" stated in the code below from the ClassProperties.java class in the org.geoserver.ows.util package. When printing the methods.getname() out I get this response:
List item
indexOf
indexOf
isFrozen
getMap
map
getCapabilities
getStyles
getLegendGraphic
capabilities
Although clazz.getMethods() gets these methods I can't find them in the code. where does Class clazz.getMethods() get them from?
ClassProperties.java
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.ows.util;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Provides lookup information about java bean properties in a class.
*
* #author Justin Deoliveira, OpenGEO
* #author Andrea Aime, OpenGEO
*
*/
public class ClassProperties {
private static final List<Method> EMPTY = new ArrayList<Method>(0);
private static final Set<String> COMMON_DERIVED_PROPERTIES = new HashSet<>(
Arrays.asList("prefixedName"));
List<Method> methods;
List<Method> getters;
List<Method> setters;
public ClassProperties(Class clazz) {
methods = Arrays.asList(clazz.getMethods());
From the class that's passed as a parameter to ClassProperties(Class clazz).
Obviously depending on the class, you'll get different methods.
The usage is simple:
ClassProperties cp = new ClassProperties(String.class);
ClassProperties cp2 = new ClassProperties(cp.getClass());
The first one would access String's methods, the second one would access the class' own methods.
If you can't see the class name in any way, the only way to find the class would be to search for all classes and check whether they have the same methods (not a very good idea).

Resources