How do I shadow SQLite DB inside fragments code with Robolectric 3.0 - robolectric

I'm trying to test my SimpleFrgament class using Roboelectric.
Now the scenario is - the fragment opens sqlite DB and fetches Page(Pojo class) from it and based on the values inside the POJO my layout is inflated.
Here is the code:
MyDb dbInstance = new MyDb(getActivity());
dbInstance.open();
Page currentPage = dbInstance.retrievePage(pageId, selectedLang);
dbInstance.close();
if (currentPage.getStatus() == null || currentPage.getStatus().size() == 0) {
llStatus.setVisibility(View.GONE);
} else {
String color = currentPage.getStatus().get(0).getColor();
if (color.equals("red"))
tvStatus.setTextColor(Color.RED);
else
tvStatus.setTextColor(Color.GREEN);
tvStatus.setText(currentPage.getStatus().get(0).getTitle());
}
Now this currentPage is obviously null and even if I fill it with some dummy values in my test code, the above piece of code will override it with null. So what is the approach to bypass the code or shadow the local database values?

Related

Multiple OnSaving event in DevExpress XAF

Im working on a piece of code using DevExpress XAF, I noticed that if im using the event OnSaving that the code executes 2 times, how can i prevent that
protected override void OnSaving()
{
if (PrestamoP != null)
{
PrestamoP.Prestado -= Monto;
PrestamoP.Save();
}
else if (PrestamoG != null)
{
PrestamoG.Prestado -= Monto;
PrestamoG.Save();
}
base.OnSaving();
}
XPO does not guarantee that the OnSaving method is called once. See the corresponding note in the XPO Best Practices article.
I can see that you are changing the PrestamoP.Prestado property based on the value of the Monto property. This code is fine if you execute it only once and only when the Monto property is specified for the first time. This code is not fine if you:
Save this object without changing the Monto property;
Update the early specified Monto value.
So, it appears that a more complex logic is required for the PrestamoG.Prestado property. First, I would move it to the Monto property setter and take the previous value into account (do not forget to check the IsLoading property in this case). Second, I would consider calculating the Prestado value dynamically instead of storing its value. This will allow you to resolve issues with the duplicate business logic execution. See an example here: How to: Calculate a Property Value Based on Values from a Detail Collection.
I can offer different methods for CRUD functions on onSaving method.
IsNewObject, IsDeleted.
// insert
if (Session.IsNewObject(this))
{
a = new a(Session);
a.CreateReferencedProperties(this);
}
// delete
else if (IsDeleted)
{
a= Session.FindObject<A>(PersistentCriteriaEvaluationBehavior.InTransaction, CriteriaOperator.Parse("A=?", this));
if (a!= null)
a.Delete();
}
// update
else
{
a= Session.FindObject<A>(PersistentCriteriaEvaluationBehavior.InTransaction, CriteriaOperator.Parse("A=?", this));
if (a!= null)
a.CreateReferencedProperties(this);
}
You can use the code below to prevent xaf from entering on saving twice.
base.OnSaving();
SessionObjectLayer sessionObjectLayer = this.Session.ObjectLayer as SessionObjectLayer;
if (sessionObjectLayer == null || sessionObjectLayer.ParentSession == null)
{
//Enter only once
}

Changelog method based on project tracker template

Based on the project tracker I have integrated a changelog into my app that relates my UserSettings model to a UserHistory model. The latter contains the fields FieldName, CreatedBy, CreatedDate, OldValue, NewValue.
The relation between both models works fine. Whenever a record is modified, I can see the changes in a changelog table. I now want add an "undo"-button to the table that allows the admin to undo a change he clicks on. I have therefore created a method that is handled by the widget that holds the changelog record:
function undoChangesToUserRecord(changelog) {
if (!isAdmin()) {
return;
}
var fieldName = changelog.datasource.item.FieldName;
var record = changelog.datasource.item.UserSettings;
record[fieldName] = changelog.datasource.item.OldValue;
}
In theory method goes the connection between UserHistory and UserSettings up to the field and rewrites its value. But when I click on the button, I get a "Failed due to circular reference" error. What am I doing wrong?
I was able to repro the issue with this bit of code:
google.script.run.ServerFunction(app.currentPage.descendants.SomeWidget);
It is kinda expected behavior, because all App Maker objects are pretty much complex and Apps Script RPC has some limitations.
App Maker way to implement it would look like this:
// Server side script
function undoChangesToUserRecord(key) {
if (!isAdmin()) {
return;
}
var history = app.models.UserHistory.getRecord(key);
if (history !== null) {
var fieldName = history.FieldName;
var settings = history.UserSettings;
settings[fieldName] = history.OldValue;
}
}
// Client side script
function onUndoClick(button) {
var history = widget.datasource.item;
google.script.run
.undoChangesToUserRecord(history._key);
}

Gosu system table query failing in Gunits

I have a Guidewire Gunit for a transformer in gosu which queries the system table to get a description for a result code which is working fine when run on the server but Gunit fails for the same.
I have tried the annotation #ServerTest for Gunit but that is failing as well.
The same code works fine in Gosu scratchpad.
PFA the code snippet as follows:
var resultCodes = Query.make(SystemTable).select().where(\elt -> elt.ResultCode == "AS01")
var description = ""
if(resultCodes != null && !resultCodes.isEmpty())
{
description = resultCodes.get(0).getFullDescription()
}
I'm getting the exception as follows :
java.lang.IllegalStateException: TableMetadataFactory cannot be used before it is started
Thanks,
Deepti
(Suggestion : )If your requirement is just to query based on some values.
Better dont use that .where() condition.
This is like SELECT * FROM <TABLE> and after getting all the data you are picking out your required result.
The best and the actual way is to use like
Query.make(TABLE_NAME).compare(TABLE_NAME#FIELD_NAME,Relop.Equals,"value_to_compare").select();
Query will be like
SELECT * FROM <TABLE_NAME> WHERE FIELD_NAME = FIELD_VALUE_TO_COMPARE;
While running Gunits, GW uses Shadow tables which will be basically empty.
Here if you are using OOTB entities, You can use Builder classes
or if you need to use some custom entities, use bundles to insert data first.
After inserting data into SystemTable (either using builder classes or bundles) run the below code.
var resultCodes = Query.make(SystemTable).compare(SystemTable#ResultCode ,Relop.Equals,"AS01").select()
foreach(result in resultCodes){
description = result.FullDescription
print("Output : "+description);
}
This happens when your RunLevel is set too low. Run levels below "NO_DAEMONS" will not load system tables. The default should be "NO_DAEMONS" so if you have an annotation on your test like this:
#RunLevel(gw.api.system.server.Runlevel.NONE)
either remove it or increase the level.
You can refactor your code like this:
uses gw.testharness.RunLevel
uses gw.api.database.Query
uses org.mockito.Mockito
uses gw.api.database.IQueryBeanResult
#RunLevel(NONE)
class StackOverflowTest {
function testDoQuery() {
var rs = Mockito.mock(IQueryBeanResult<SystemTable>)
var query = Mockito.mock(Query<SystemTable>)
Mockito.when(query.select()).thenReturn(rs)
var stackOverflow = Mockito.spy(new StackOverflow())
Mockito.doReturn(query).when(stackOverflow).getSystemTableQuery()
stackOverflow.doQuery()
Mockito.verify(stackOverflow, Mockito.times(1)).getSystemTableQuery()
Mockito.verify(query, Mockito.times(1)).select()
Mockito.verify(rs, Mockito.times(1)).iterator()
}
class StackOverflow {
function doQuery() {
var resultCodes = getSystemTableQuery().select().where(\elt -> elt.ResultCode == "AS01")
}
protected function getSystemTableQuery(): Query<SystemTable> {
return Query.make(SystemTable)
}
}
}

Create a new record in form LedgerJournalTransCustPaym through x++ code

I need to create a reord in LedgerJournalTrans through x++ code.
While debugging I found out that the class LedgerJournalEngine_CustPayment is used to initiate the form as
LedgerJournalEngine_CustPayment = new LedgerJournalEngine_CustPayment(element)
and later
LedgerJournalEngine.initValue(LedgerJournalTrans);
also after assiging the accountNum the methods executed at the modified() method of datasource field LedgerJournalTrans:AccountNum are element.accountNumModifiedPost(); etc.
While trying to achieve the same through code I am not able to initiate the class LedgerJournalEngine_CustPayment and also the other methods in the form LedgerJournalTransCustPaym that system does.
Pls Help..
Joyce
LedgerJournalEngine* classes are mostly used by the forms to do work and execute code before/after events and datasource actions. What you're trying to do, it would probably just make more sense to complete all of the necessary ledgerJournalTrans fields, then do a .insert(). Here is some code I wrote that will do what you want though using the engine some:
static void Job81(Args _args)
{
LedgerJournalEngine_CustPayment ledgerJournalEngine;
LedgerJournalTable ledgerJournalTable;
LedgerJournalTrans ledgerJournalTrans;
NumberSeq numberSeq;
Voucher voucher;
;
// This just selects the header you are inserting into
select firstonly ledgerJournalTable where ledgerJournalTable.JournalNum == 'GB 0056226';
if (!ledgerJournalTable)
throw error ("Unable to find journal table record");
ledgerJournalTrans.initValue();
numberSeq = NumberSeq::newGetNumFromCode(ledgerJournalTable.VoucherSeries);
if (numberSeq)
{
ledgerJournalTrans.Voucher = numberSeq.num();
voucher = ledgerJournalTrans.Voucher;
}
ledgerJournalTrans.JournalNum = ledgerJournalTable.JournalNum;
ledgerJournalTrans.TransDate = SystemDateGet();
ledgerJournalTrans.AccountType = LedgerjournalACType::Cust;
ledgerJournalTrans.AccountNum = '100003';
ledgerJournalEngine = LedgerJournalEngine::construct(LedgerJournalType::CustPayment);
ledgerJournalEngine.newJournalActive(ledgerJournalTable);
ledgerJournalEngine.accountModified(ledgerJournalTrans);
ledgerJournalTrans.AmountCurCredit = 10;
ledgerJournalTrans.OffsetAccountType = ledgerJournalTable.OffsetAccountType;
ledgerJournalTrans.OffsetAccount = ledgerJournalTable.OffsetAccount;
ledgerJournalTrans.CurrencyCode = CompanyInfo::standardCurrency();
ledgerJournalEngine.currencyModified(ledgerJournalTrans);
ledgerJournalTrans.insert();
if (numberSeq && ledgerJournalTrans.Voucher == voucher)
{
numberSeq.used();
}
else
{
if (numberSeq)
numberSeq.abort();
}
info("Done");
}

Saving changes of Entity Framework in Asp.Net

I have created an entity Appraiser and there are methods to select values, display data etc.
Now I want to save the changes made after data is displayed, I have a button named SAVE, which will be used to save changes.
I am not able to get how to save the changes of this Entity?
Entity name is Appraiser, and I have created methods like get AppriaserDetails etc in DAL, BL and used them in aspx.cs.
This is my code:
public void UpdateData(Appraiser appId)
{
var Appsave = context.Appraisers.FirstOrDefault(App => App.AppraiserId == appId.AppraiserId);
Appsave.AppraiserName = appId.AppraiserName;
Appsave.AppraiserPhones = appId.AppraiserPhones;
Appsave.AppraiserAppraiserCompanyId = appId.AppraiserAppraiserCompanyId;
Appsave.Address = appId.Address;
Appsave.City = appId.City;
Appsave.ProvinceState = appId.ProvinceState;
Appsave.Email = appId.Email;
context.SaveChanges();
}
If u want to insert new record, then can use
MyContext.Appraisers.AddObject(appraiserEntityObject);
MyContext.SaveChanges();
In case of update
if (appraiserEntityObject.EntityState == EntityState.Detached)
{
// In case of web, we got an existing record back from the browser. That object is not attached to the context yet.
MyContext.Appraisers.Attach(appraiserEntityObject);
MyContext.ObjectStateManager.ChangeObjectState(appraiserEntityObject, EntityState.Modified);
}
MyContext.SaveChanges();
Here MyContext is ur ObjectContext

Resources