I am setting up an Spring boot application on Jenkins. For the unit tests i am getting below error. This error is not particular to one test cases. Every time I run it is giving me error for different test. I am not sure what is wrong. Same project is working fine (build and unit tests) on local and other environments like (development, stage). Any idea with below errors?
00:49:42.836 [main] DEBUG org.springframework.test.context.support.ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [com.abc.services.tokens.crypto.aws.AesGcmDynamoCryptoCipherProviderTest]
00:49:42.836 [main] INFO org.springframework.test.context.support.DefaultTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener#43195e57, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener#333291e3, org.springframework.test.context.support.DependencyInjectionTestExecutionListener#479d31f3, org.springframework.test.context.support.DirtiesContextTestExecutionListener#40ef3420]
Here is the test class
#SuppressWarnings("unchecked")
public class AesGcmDynamoCryptoCipherProviderTest extends AbstractTestNGBeanMockingTests {
#MockBean
AwsCrypto awsCrypto;
#MockBean
DynamoDBProvider dynamoDBProvider;
#MockBean
MasterKeyProvider masterKeyProvider;
#MockBean
Table table;
private static Item mockCipherItem(UUID cipherId) {
Item item = mock(Item.class);
return item;
}
private static <T> CryptoResult<T, ?> mockCryptoResult(T result) {
// do something
return cryptoResult;
}
#BeforeMethod
private void init() {
CryptoResult<String, ?> decryptoResult = mockCryptoResult(Base64.getEncoder().encodeToString("*decrypted*".getBytes()));
CryptoResult<String, ?> encryptoResult = mockCryptoResult("*encrypted*");
}
#Test
public void testGetCipher() {
AesGcmDynamoCryptoCipherProvider provider = new AesGcmDynamoCryptoCipherProvider("table", awsCrypto, dynamoDBProvider, masterKeyProvider);
UUID cipherId = UUID.randomUUID();
Item cipherItem = mockCipherItem(cipherId);
AesGcmCipher cipher = provider.getCipher(cipherId);
assertNotNull(cipher);
assertEquals(cipher.getCipherId(), cipherId);
}
}
Base class
#ContextConfiguration(classes = { //...
AbstractTestNGBeanMockingTests.MockBeanConfiguration.class //...
})
#DirtiesContext
public class AbstractTestNGBeanMockingTests extends AbstractTestNGSpringContextTests {
private static ThreadLocal<Class<? extends AbstractTestNGBeanMockingTests>> currentTestClass = new ThreadLocal<>();
#AfterClass(alwaysRun = true)
#Override
protected void springTestContextAfterTestClass() throws Exception {
super.springTestContextAfterTestClass();
}
#BeforeClass(alwaysRun = true, dependsOnMethods = { "springTestContextBeforeTestClass" })
#Override
protected void springTestContextPrepareTestInstance() throws Exception {
currentTestClass.set(this.getClass());
super.springTestContextPrepareTestInstance();
currentTestClass.set(null);
}
#BeforeMethod
public void initializeMockedBeans() {
MockBeanRegistration.initializeMockedBeans(this);
}
protected static class MockBeanConfiguration {
MockBeanConfiguration(ApplicationContext context) {
MockBeanRegistration.registerMocks((BeanDefinitionRegistry) context, currentTestClass.get());
}
}
}
I have bumped into this error after moving classes into new packages somewhere under the java folder, but omitting to move the corresponding test classes in the test folders.
After applying the changes in the test packages as well, it runs again.
You wrote that you experience the problem only in the Jenkins environment.
My guess is that Jenkins starts always with a new checkout of the project from a 100% clean status. In the other environments you might have some residues from the previous development, and these somehow allow the tests to 'work', but I would expect that it is Jenkins getting it right...
Try to setup the app in a development environment from scratch. If you get the error, so you will properly analyze it and correct it.
Related
Looking at the Arquillian documentation, I am aware that I can use the #ArquillianSuiteDeployment and #Deployment annotations to deploy my desired jars/wars to the container. Example:
#ArquillianSuiteDeployment
public class MyDeployer {
#Deployment(name = "myapp", order = 1, testable = false)
public static Archive<?> myDeploymentJar() {
final File file = Maven.configureResolver().fromFile(System.getProperty("settings.xml"))
.loadPomFromFile("pom.xml").resolve("com.myapp:test-app").withoutTransitivity()
.asSingleFile();
final JavaArchive jar = ShrinkWrap.createFromZipFile(JavaArchive.class, file);
final JavaArchive archive = ShrinkWrap.create(JavaArchive.class, "test-app.jar").merge(jar);
return archive;
}
}
Let's infer that I have two more jars that I would like to deploy, but never together during the same test, JAR-A and JAR-C.
#Test
#RunAsClient
public void testOne() {
// deploy JAR-A before all others, but do not deploy JAR-C
}
#Test
#RunAsClient
public void testTwo() {
// deploy JAR-C before all others, but do not deploy JAR-A
}
Is it possible to introduce a conditional #Deployment that would go along with my tests?
That's an interesting usecase.
Deployments happen before execution of the tests so it's not possible at the moment to achieve it just by using annotations.
You can, however, programmatically control deployments using Deployer service.
#Deployment(name = "JAR-C", managed = false)
public static WebArchive create() {
return ShrinkWrap.create(JavaArchive.class);
}
#ArquillianResource
private Deployer deployer;
#Test
public void should_work() {
deployer.deploy("JAR-C");
// test
deploy.undeploy("JAR-C");
}
Important fact is that you have to instruct Arquillian to not manage this deployment for you, that's what managed = false flag is for in #Deployment(name = "X", managed = false).
Hope that helps.
I'm trying to search for an example of how to run a tests suite for test classes that use Robolectric, for example I have this class:
#Config(sdk = 16, manifest = "src/main/AndroidManifest.xml")
#RunWith(RobolectricTestRunner.class)
public class RestaurantModelTest {
//setUp code here...
#Test
public void testFindByLocation() throws Exception {
//test code here
}
}
All unit test and assertions of class RestaurantModelTest are passing, but I also have another class lets call it XModelTest (in which all assertions and unit test are passing.
My problem
I don't find any tutorial/example of how to use a test suite using robolectric.
Should this be done in the same package where my RestaurantModelTest and XModelTest are? If not where?
Also I tried doing this with TestSuite from JUnit but many questions arise should the class with my TestSuite extend extends TestSuite super class?
If someone can give me a short example using my RestaurantModelTestand XModelTestclasses it would be great.
I believe, I've also partially covered this question answering your second question - Can't run android test suite: Exception in thread “main”
Here's how to write a suite with Robolectric:
Let's say we have 2 model classes.
CartModel.java
public class CartModel {
public float totalAmount;
public int products;
public void addToCart(float productPrice) {
products++;
totalAmount += productPrice;
}
}
and RestaurantModel.java
public class RestaurantModel {
public int staff;
public void hire(int numberOfHires) {
staff += numberOfHires;
}
}
Let's write some dummy tests for them:
CartModelTest.java
#RunWith(RobolectricGradleTestRunner.class)
#Config(constants = BuildConfig.class, sdk=21)
public class CartModelTest {
#Test
public void addToCart() throws Exception {
CartModel cartModel = new CartModel();
assertEquals(0, cartModel.totalAmount, 0);
assertEquals(0, cartModel.products);
cartModel.addToCart(10.2f);
assertEquals(10.2f, cartModel.totalAmount, 0);
assertEquals(1, cartModel.products);
}
}
RestaurantModelTest.java
#RunWith(RobolectricGradleTestRunner.class)
#Config(constants = BuildConfig.class, sdk=21)
public class RestaurantModelTest {
#Test
public void hire() throws Exception {
RestaurantModel restaurantModel = new RestaurantModel();
assertEquals(0, restaurantModel.staff);
restaurantModel.hire(1);
assertEquals(1, restaurantModel.staff);
}
}
And now last step - to group them together into one ModelsTestSuite.java:
#RunWith(Suite.class)
#Suite.SuiteClasses({
RestaurantModelTest.class,
CartModelTest.class
})
public class ModelsTestSuite {}
To run - just right-click in ModelsTestSuite and click "Run ModelsTestSuite". That's it!
NB! In Android Studio 2.0 3b, you have to disable instant run (Preferences -> Build, Execution, Deployment -> Instant Run -> Enable Instant Run - uncheck) in order to run Robolectric tests (to avoid java.lang.RuntimeException: java.lang.ClassNotFoundException: Could not find a class for package: <package name> and class name: com.android.tools.fd.runtime.BootstrapApplication).
I hope, it helps
My project is not Spring based .Its a java with Hibernate.Building tool - Maven.
I am loading data from one database to HSQL DB before running junits.
My DB util class:
public class DatabaseUtil {
SchemaLoad schemaLoad = new SchemaLoad();
DataLoad dataLoad = new DataLoad();
boolean dataLoaded = false;
static final String filename1 = "test1.txt";
static final String filename2 = "text2.txt";
void dbLoad() throws SQLException {
if (!dataLoaded) {
schemaLoad.cloneSchema(filename1);
dataLoad.exportData(filename2);
System.out.println("***********executed**********8");
dataLoaded = true;
}
}
}
First Test Case:
public class TestCase {
TrainRepository trainRepository = new TrainRepositoryImpl();
DatabaseUtil databaseUtil = new DatabaseUtil();
#BeforeClass
private void setUp() throws SQLException {
databaseUtil.dbLoad();
}
#Test
private void positiveTestCaseForTrainRepo() throws Exception {
//TestCases
}
Second Test case:
public class TestCase1 {
AirRepository airRepository = new AirRepositoryImpl();
DatabaseUtil databaseUtil = new DatabaseUtil();
#BeforeClass
private void setUp() throws SQLException {
databaseUtil.dbLoad();
}
#Test
private void positiveTestCaseForAirRepo() throws Exception {
//TestCases
}
Both the test cases are running fine.But Its executing databaseUtil.dbLoad(); method on each junit.
My question is I need to load the database only once ie before start of first junit and need to set some indicator .The further junits need to check the DB instance If DB instance is there it should not load the data ie DatabaseUtil class need to be singleton.
All the junits are running through maven suffire plugin during mvn install phase.
Kindly help me to achieve this.
void dbLoad() will be called each time.
then use a static variable to keep track
static boolean dataLoaded = false;
if you don't use spring you need to implement caching yourself. you have a few option. use static field with some kind of synchronization (in case you use/plan to use threads). other option is to switch to testng that gives you #BeforeGroup functionality so you can mark all your db tests and have your initialization run before.
I have an OSGi bundle which reads some properties from the config.properties file of Apache Felix during the activation process, and if this configuration is malformed or absent then the bundle should not start. For this, I am creating its respective Unit Test, I am using Arquillian for the tests. The problem arises when I want to provide different types of conf.properties to different Arquillian tests, in order to cover each scenario.
When Arquillian runs the tests it load a framework.properties file from the /test/resources/ folder to initialize Apache Felix, install the test bundles and run the tests. Now, my question is how can I provide a different framework.properties file for each test case?
Here is the Arquillian Unit Test I use:
#RunWith(Arquillian.class)
public class PersistenceLoaderTest {
#Deployment
public static Archive<?> createDeployment() {
final JavaArchive archive = ShrinkWrap.create(JavaArchive.class, "persistence-arq.jar");
archive.addClass(ProviderLoader.class);
archive.setManifest(new Asset() {
public InputStream openStream() {
OSGiManifestBuilder builder = OSGiManifestBuilder.newInstance();
builder.addBundleSymbolicName(archive.getName());
builder.addBundleManifestVersion(2);
builder.addImportPackages("org.osgi.service.startlevel", "org.osgi.service.url");
builder.addImportPackages(ProviderLoader.class);
return builder.openStream();
}
});
return archive;
}
#ArquillianResource
public Bundle bundle;
#ArquillianResource
BundleContext bundleContext;
#Test
public void loadFrameworkConfiguration(){
// What goes here?
}
}
And the framework.properties file:
# The Felix Framewok log level
#
# ERROR = 1;
# WARNING = 2;
# INFO = 3;
# DEBUG = 4;
felix.log.level=4
org.domain.database=mydb
org.domain.driver=org.hsqldb.jdbcDriver
org.domain.url=jdbc:hsqldb:file:
org.domain.username=sa
org.domain.password=
These are the property values I need to change and test them for different scenarios.
To my understanding this is Container level properties and not Deployment level properties, so you would need to restart the container for it to take effect.
You could achieve this by setting the Container mode in arquillian.xml to manual.
<arquillian>
<container qualifier="manual_felix" mode="manual">
</container>
</arquillian>
Then in a TestClass you can inject the ContainerController and start it with new properties for each run.
#RunWith(Arquillian.class)
public class TestA {
#Deployment(name = "x", managed = false) #TargetsContainer("manual_felix")
public static Archive<?> deployment() {
return ShrinkWrap.create....
}
#ArquillianResource
private ContainerController cc;
#ArquillianResource
private Deployer d;
#Test #InSequence(1)
public void start() {
cc.start("manual_felix", new Config().add("frameworkProperties", "my-custom-properties-file"));
d.deploy("x");
}
#Test #InSequence(2) #OperatesOnDeployment("x")
public void shouldDoSomethingInsideX() {
// executes inside container in context of X
}
}
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.