dropDatabase from spring mongo - spring-data-mongodb

I would like to dropDatabase in my mongo before my integration tests. Is it possible to do this through spring mongo ?
If it's not available for now, is it possible on fetching the com.mongodb.DB object somehow from spring mongo, so i can invoke it's dropDatabase() ?

Just in case someone needs the info, notice that since 3.0 there is no dropDatabase() method in the MongoDatabase api, so you have to write this instead:
mongoTemplate.getDb().drop();
>> source <<

A slightly cleaner solution which I am using is to use the MongoDbFactory object, as below:
mongoDbFactory.getDb().dropDatabase();

Found it at last !
From mongodb shell :
> db.dropDatabase
function () {
if (arguments.length) {
throw "dropDatabase doesn't take arguments";
}
return this._dbCommand({dropDatabase:1});
}
combined with mongoOperations' executeCommand :
#Autowired private MongoOperations ops;
#BeforeMethod
public void dropDb() {
this.ops.executeCommand("{dropDatabase:1}");
}

mongoTemplate.getDb().dropDatabase();

Related

Can I use mongock with Spring Data Repositories?

I tried to inject with #Autowired annotation a repository into changelog
and it doesn't get injected.
Config uses spring application context
#Bean
public SpringBootMongock mongock(ApplicationContext springContext, MongoClient mongoClient) {
return new SpringBootMongockBuilder(mongoClient, "yourDbName", "com.package.to.be.scanned.for.changesets")
.setApplicationContext(springContext)
.setLockQuickConfig()
.build();
}
And the changelog
#ChangeLog(order = "001")
public class MyMigration {
#Autowired
private MyRepository repo;
#ChangeSet(order = "001", id = "someChangeId", author = "testAuthor")
public void importantWorkToDo(DB db){
repo.findAll() // here null pointer
}
}
firstly, notice that if you are using repositories in your changelogs, it's a bad practice to use it for writes, as it won't be covered by the lock mechanism(this is feature is coming soon), only for reads.
To inject your repository(or any other dependency) you simply need to inject it in your changeSet method signature, like this:
#ChangeLog(order = "001")
public class MyMigration {
#ChangeSet(order = "001", id = "someChangeId", author = "testAuthor")
public void importantWorkToDo(MongoTemplate template, MyRepository repo){
repo.findAll(); this should work
}
}
Notice that you should use the last version(at this moment 3.2.4) and DB class is not supported anymore. Please use MongoDatabase or MongoTemplate(preferred).
Documentation to Mongock
we have recently released the version 4.0.7.alpha, which among other things allows you to use Spring repositories(and any other custom bean you wish) in your changeSets with no problem. You can insert, update, delete and read. It will be safely covered by the lock.
The only restriction is that it needs to be an interface, which should be the common case for Spring repositories.
Please take a look to this example

Hystrix Javanica : Call always returning result from fallback method.(java web app without spring)

I am trying to integrate Hystrix javanica into my existing java EJB web application and facing 2 issues with running it.
When I try to invoke following service it always returns response from fallback method and I see that the Throwable object in fallback method has "com.netflix.hystrix.exception.HystrixTimeoutException" exception.
Each time this service is triggered, HystrixCommad and fallback methods are called multiple times around 50 times.
Can anyone suggest me with any inputs? Am I missing any configuration?
I am including following libraries in my project.
project libraries
I have setup my aspect file as follows:
<aspectj>
<weaver options="-verbose -showWeaveInfo"></weaver>
<aspects>
<aspect name="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"/>
</aspects>
</aspectj>
Here is my config.properties file in META-INF/config.properties
hystrix.command.default.execution.timeout.enabled=false
Here is my rest service file
#Path("/hystrix")
public class HystrixService {
#GET
#Path("clusterName")
#Produces({ MediaType.APPLICATION_JSON })
public Response getClusterName(#QueryParam("id") int id) {
ClusterCmdBean clusterCmdBean = new ClusterCmdBean();
String result = clusterCmdBean.getClusterNameForId(id);
return Response.ok(result).build();
}
}
Here is my bean class
public class ClusterCmdBean {
#HystrixCommand(groupKey = "ClusterCmdBeanGroup", commandKey = "getClusterNameForId", fallbackMethod = "defaultClusterName")
public String getClusterNameForId(int id) {
if (id > 0) {
return "cluster"+id;
} else {
throw new RuntimeException("command failed");
}
}
public String defaultClusterName(int id, Throwable e) {
return "No cluster - returned from fallback:" + e.getMessage();
}
}
Thanks for the help.
If you want to ensure you are setting the property, you can do that explicitly in the circuit annotation itself:
#HystrixCommand(commandProperties = {
#HystrixProperty(name = "execution.timeout.enabled", value = "false")
})
I would only recommend this for debugging purposes though.
Something that jumps out to me is that Javanica uses AspectJ AOP, which I have never seen work with new MyBean() before. I've always have to use #Autowired with Spring or similar to allow proxying. This could well just be something that is new to me though.
If you set a breakpoint inside the getClusterNameForId can you see in the stack trace that its being called via reflection (which it should be AFAIK)?
Note you can remove commandKey as this will default to the method name. Personally I would also remove groupKey and let it default to the class name.

Unable to return collections or arrays from JAX-WS Web Service

I found that I was unable to return collections from my JAX-WS Web Service.
I appreciate that the Java Collections API may not be supported by all clients, so I switched to return an array, but I can't seem to do this either.
I've set up my web service as follows:
#WebService
public class MyClass {
public ReturnClass[] getArrayOfStuff() {
// extremely complex business logic... or not
return new ReturnClass[] {new ReturnClass(), new ReturnClass()};
}
}
And the ReturnClass is just a POJO. I created another method that returns a single instance, and that works. It just seems to be a problem when I use collections/arrays.
When I deploy the service, I get the following exception when I use it:
javax.xml.bind.MarshalException - with linked exception:
[javax.xml.bind.JAXBException: [LReturnClass; is not known to this context]
Do I need to annotate the ReturnClass class somehow to make JAX-WS aware of it?
Or have I done something else wrong?
I am unsure of wheter this is the correct way to do it, but in one case where I wanted to return a collection I wrapped the collection inside another class:
#WebService
public class MyClass {
public CollectionOfStuff getArrayOfStuff() {
return new CollectionOfStuff(new ReturnClass(), new ReturnClass());
}
}
And then:
public class CollectionOfStuff {
// Stuff here
private List<ReturnClass> = new ArrayList<ReturnClass>();
public CollectionOfStuff(ReturnClass... args) {
// ...
}
}
Disclaimer: I don't have the actual code in front of me, so I guess my example lacks some annotations or the like, but that's the gist of it.

Android Unit Tests Requiring Context

I am writing my first Android database backend and I'm struggling to unit test the creation of my database.
Currently the problem I am encountering is obtaining a valid Context object to pass to my implementation of SQLiteOpenHelper. Is there a way to get a Context object in a class extending TestCase? The solution I have thought of is to instantiate an Activity in the setup method of my TestCase and then assigning the Context of that Activity to a field variable which my test methods can access...but it seems like there should be an easier way.
You can use InstrumentationRegistry methods to get a Context:
InstrumentationRegistry.getTargetContext() - provides the application Context of the target application.
InstrumentationRegistry.getContext() - provides the Context of this Instrumentation’s package.
For AndroidX use InstrumentationRegistry.getInstrumentation().getTargetContext() or InstrumentationRegistry.getInstrumentation().getContext().
New API for AndroidX:
ApplicationProvider.getApplicationContext()
You might try switching to AndroidTestCase. From looking at the docs, it seems like it should be able to provide you with a valid Context to pass to SQLiteOpenHelper.
Edit:
Keep in mind that you probably have to have your tests setup in an "Android Test Project" in Eclipse, since the tests will try to execute on the emulator (or real device).
Your test is not a Unit test!!!
When you need
Context
Read or Write on storage
Access Network
Or change any config to test your function
You are not writing a unit test.
You need to write your test in androidTest package
Using the AndroidTestCase:getContext() method only gives a stub Context in my experience. For my tests, I'm using an empty activity in my main app and getting the Context via that. Am also extending the test suite class with the ActivityInstrumentationTestCase2 class. Seems to work for me.
public class DatabaseTest extends ActivityInstrumentationTestCase2<EmptyActivity>
EmptyActivity activity;
Context mContext = null;
...
#Before
public void setUp() {
activity = getActivity();
mContext = activity;
}
... //tests to follow
}
What does everyone else do?
You can derive from MockContext and return for example a MockResources on getResources(), a valid ContentResolver on getContentResolver(), etc. That allows, with some pain, some unit tests.
The alternative is to run for example Robolectric which simulates a whole Android OS. Those would be for system tests: It's a lot slower to run.
You should use ApplicationTestCase or ServiceTestCase.
Extending AndroidTestCase and calling AndroidTestCase:getContext() has worked fine for me to get Context for and use it with an SQLiteDatabase.
The only niggle is that the database it creates and/or uses will be the same as the one used by the production application so you will probably want to use a different filename for both
eg.
public static final String NOTES_DB = "notestore.db";
public static final String DEBUG_NOTES_DB = "DEBUG_notestore.db";
First Create Test Class under (androidTest).
Now use following code:
public class YourDBTest extends InstrumentationTestCase {
private DBContracts.DatabaseHelper db;
private RenamingDelegatingContext context;
#Override
public void setUp() throws Exception {
super.setUp();
context = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_");
db = new DBContracts.DatabaseHelper(context);
}
#Override
public void tearDown() throws Exception {
db.close();
super.tearDown();
}
#Test
public void test1() throws Exception {
// here is your context
context = context;
}}
Initialize context like this in your Test File
private val context = mock(Context::class.java)

Basic NMock database examples for CRUD application

I'm looking for some basic examples of using NMock2 to mock database calls for a CRUD application.
Thanks,
Chris
Setup:
[SetUp]
public void SetUp()
{
mocks = new Mockery();
mockDBLayer = _mocks.NewMock<IDBLayer>();
//Inject the dependency somehow
sut = new SUT(_mockDBLayer );
}
Test:
[Test]
public void testMethodName_TestCase()
{
var dbRetrunValue = //whatever type
Expect.Once.On(mockDBLayer).Method("dbMethod").Will(Return.Value(dbRetrunValue));
//exercise
var actual = sut.methodName();
//Assert
...
}
Verification if you want it
[TearDown]
public void TearDown()
{
mocks.VerifyAllExpectationsHaveBeenMet();
}
I like Moq better however:
http://code.google.com/p/moq/
"database calls" is a rough term to guess at - do you mean testing your DAL, or testing a layer above that?
If you mean testing your DAL, you need to look at how you're getting the actual DataReader or DataTable, or whatever, so that you can replace it with the mock.
See blog posts like this that covers IoC and mocking data access , or posts like this that cover mocking a datareader for getting started.

Resources