How to test #future methods - salesforce

I've the following services:
public with sharing class LibraryService {
public static void remove(String jsonString) {
Library__c library = [ SELECT Id, ilms__Library_Name__c FROM ilms__Library__c WHERE Id = libraryId ] ;
AccessService.deleteReviewerGroup(library);
delete library;
}
}
AccessService class
public with sharing class AccessService {
public static void deleteLibraryReviewerGroup(Library__c library) {
List<Library__Share> reviewersGroups = [ SELECT UserOrGroupId FROM ilms__Library__Share WHERE AccessLevel = 'Read' AND ParentId = :library.Id ];
System.debug('reviewersGroups: ' + reviewersGroups);
if(reviewersGroups.size() == 1) {
String reviewersGroupId = reviewersGroups[0].UserOrGroupId;
delete reviewersGroups;
AccessService.deleteReviewerGroup(reviewersGroupId);
}
return;
}
#future
public static void deleteReviewerGroup(String groupId) {
List<Group> reviewerGroup = [ SELECT Id FROM Group WHERE Id = :groupId ];
delete reviewerGroup;
}
}
Now, when I try to test the LibraryService remove method, I keep receiving the below error:
first error: MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa).
#isTest(SeeAllData=true)
private class TestLibrary {
static testMethod void testRemoveLibrary() {
Library__c library = new Library__c(...);
Boolean isRemoved = LibraryService.remove(TestUtilsClass.idJson(library.Id));
System.assertEquals(isRemoved, true);
}
}
I tried adding Test.startTest() and Test.stopTest() to the testRemoveLibrary method, but I still get the same error. Am I doing something wrong? How do I fix this?

#isTest(SeeAllData=true)
private class TestLibrary {
static testMethod void testRemoveLibrary() {
Library__c library = new Library__c(...);
Test.start();
Boolean isRemoved = LibraryService.remove(TestUtilsClass.idJson(library.Id));
Test.stop();
System.assertEquals(isRemoved, true);
}
}
Please add Test.start and stop including your method.

Related

How to get Android Context using Robolectric 4.3.1

Trying to use Robolectric 4.3.1 to do the most basic of Android actions, get the Context.
I get a non-null context by doing this (tried many other attempts but all end up getting context = null):
Context context = RuntimeEnvironment.systemContext;
I can pass the object into some methods but I can never use it.
If I try
File dir = context.getFilesDir();
I get
java.lang.RuntimeException: No data directory found for package android
What am I doing wrong?
Here is my code:
#RunWith(RobolectricTestRunner.class)
#Config(sdk = Build.VERSION_CODES.O)
public class BtScannerTests
{
private BluetoothAdapter bluetoothAdapter;
#Before
public void setUp() throws Exception
{
bluetoothAdapter = Shadow.newInstanceOf(BluetoothAdapter.class);
}
private static boolean done = false;
#Test
public void testBtScannerCycle() throws InterruptedException
{
IntermediaryCallback intermediaryCallback = new IntermediaryCallback()
{
#Override
public void onReceiveMdsIntermediary(MdsIntermediary mds, int connectionHandle)
{
}
#Override
public void onReceiveMetricIntermediaries(List<MetricIntermediary> metricList, MdsIntermediary mds, int connectionHandle)
{
}
};
StatusEventCallback statusEventCallback = new StatusEventCallback()
{
#Override
public void onStatusEvent(StatusEvent statusEvent, int connectionHandle, String btAddress)
{
System.out.println("Status event " + statusEvent.name());
if(statusEvent == StatusEvent.SCANNING_PAUSED);
{
done = true;
}
}
};
Context context = RuntimeEnvironment.systemContext;
File dir = context.getFilesDir(); // This is the code that fails; put here to test attempts
AndroidBtManager.setStatusEventCallback(statusEventCallback);
AndroidBtManager androidBtManager =
new AndroidBtManager(context, intermediaryCallback, false, false, true);
BtScanner btScanner = androidBtManager.getBtScanner();
while(!done)
{
Thread.sleep(1000);
}
}
}
Use this one.
Context context = ApplicationProvider.getApplicationContext();
instead of
Context context = RuntimeEnvironment.systemContext;

testng how to dynamically set groups from Factory?

Before I setup a test class like the code below:
1. the Factory and test Dataprovider both used excel as the dataprovider.
2. In the Factory dataprovider table, it has a list of url
3. Each time, it will find one of the url in the factory dataprovider table, and run the test in each test methods..
public class Test {
WebDriver driver;
private String hostName;
private String url;
#Factory(dataProvider = "xxxx global variables", dataProviderClass = xxxx.class)
public GetVariables(String hostName, String url) {
this.hostName = hostName;
this.url = url;
}
#BeforeMethod
#Parameters("browser")
public void start(String browser) throws Exception {
driver = new FirefoxDriver();
driver.get(url);
Thread.sleep(1000);
}
#Test(priority = 10, dataProvider = "dataprovider Test A", dataProviderClass = xxx.class)
public void TestA(Variable1,
Variable2,Variable3) throws Exception {
some test here...
}
#Test(priority = 20, dataProvider = "dataprovider Test B", dataProviderClass = xxx.class)
public void TestB(Variable1,
Variable2,Variable3)
throws Exception {
some test here...
}
#AfterMethod
public void tearDown() {
driver.quit();
}
Now I want to dynamically assign different group for each test for different url. I am thinking add a variable 'flag' in the #Factory dataprovider:
#Factory(dataProvider = "xxxx global variables", dataProviderClass = xxxx.class)
public GetVariables(String hostName, String url, String flag) {
this.hostName = hostName;
this.url = url;
this.flag = flag;
}
That when flag.equals("A"), it will only run test cases in test groups={"A"}.
When flag.equals("B"), it will only run test cases in test groups ={"B"},
When flag.equals("A,B"), it will only run test cases in test groups ={"A","B"}
Is there any way I can do that?
Thank you!
TestNG groups provides "flexibility in how you partition your tests" but it isn't for conditional test sets. For that you simply use plain old Java.
You can use inheritance or composition (I recommend the latter, see Item 16: Favor composition over inheritance from Effective Java).
Either way the general idea is the same: use a Factory to create your test class instances dynamically creating the appropriate class type with the appropriate test annotations and/or methods that you want to run.
Examples:
Inheritance
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class DemoTest {
#Factory
public static Object[] createTests() {
return new Object[]{
new FlavorATest(),
new FlavorBTest(),
new FlavorABTest()
};
}
/**
* Base test class with code for both A-tests and B-tests.
*
* Note that none of these test methods are annotated as tests so that
* subclasses may pick which ones to annotate.
*/
public static abstract class BaseTest {
protected void testA() {
// test something specific to flavor A
}
protected void testB() {
// test something specific to flavor B
}
}
// extend base but only annotate A-tests
public static class FlavorATest extends BaseTest {
#Test
#Override
public void testA() {
super.testA();
}
}
// extend base but only annotate B-tests
public static class FlavorBTest extends BaseTest {
#Test
#Override
public void testB() {
super.testB();
}
}
// extend base and annotate both A-tests and B-tests
public static class FlavorABTest extends BaseTest {
#Test
#Override
public void testA() {
super.testA();
}
#Test
#Override
public void testB() {
super.testB();
}
}
}
Composition
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class DemoTest {
#Factory
public static Object[] createTests() {
return new Object[]{
new FlavorATest(),
new FlavorBTest(),
new FlavorABTest()
};
}
private static void testA() {
// test something specific to flavor A
}
private static void testB() {
// test something specific to flavor B
}
// only create A-test methods and delegate to shared code above
public static class FlavorATest {
#Test
public void testA() {
DemoTest.testA();
}
}
// only create B-test methods and delegate to shared code above
public static class FlavorBTest {
#Test
public void testB() {
DemoTest.testB();
}
}
// create A-test and B-test methods and delegate to shared code above
public static class FlavorABTest {
#Test
public void testA() {
DemoTest.testA();
}
#Test
public void testB() {
DemoTest.testB();
}
}
}
Your factory methods won't be as simple as you'll need to use your "flag" from your test data to switch off of and create instances of the appropriate test classes.

Map a Uri field using Dapper

What is the cleanest way to map a string column to a Uri property using Dapper?
Here's the cleanest I've been able to come up with so far (using the ITypeMap functionality):
Query:
SELECT * FROM TableWithAStringAddressColumn
POCO:
public class MyPoco
{
[ColumnSetter("DapperAddress")]
public Uri Address { get; set; }
private string DapperAddress { set { this.Address = new Uri(value); } }
}
Extensions:
partial class SqlMapper
{
public static void InitializeTypeMaps()
{
SqlMapper.SetTypeMap(
typeof(MyPoco),
new CustomPropertyTypeMap(typeof(MyPoco), SqlMapper.CustomSetterMapper));
// call out every other class that needs this kind of mapping
}
public static Func<Type, string, PropertyInfo> CustomSetterMapper =
(type, columnName) =>
{
PropertyInfo prop = type
.GetProperties()
.FirstOrDefault(p => string.Equals(columnName, p.Name, StringComparison.OrdinalIgnoreCase));
if (prop != null)
{
// find out if we need to use a different setter
ColumnSetterAttribute setterAttribute = prop.GetCustomAttributes(false).OfType<ColumnSetterAttribute>().LastOrDefault();
if (setterAttribute != null)
{
PropertyInfo setterProp = type
.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.FirstOrDefault(p => string.Equals(setterAttribute.Setter, p.Name, StringComparison.OrdinalIgnoreCase));
if (setterProp == null)
{
throw new InvalidOperationException(string.Format("Setter property misconfigured (Property={0}, Setter={1})", prop.Name, setterAttribute.Setter));
}
else
{
prop = setterProp;
}
}
}
return prop;
};
}
Custom Attribute:
public class ColumnSetterAttribute : Attribute
{
public string Setter { get; set; }
public ColumnSetterAttribute(string setter)
{
this.Setter = setter;
}
}
[edit] I'm looking for a solution I can use without needing to call out all columns in all my queries (I'd like to find a solution where I can use SELECT *).
Seems like a lot of work...
Wouldn't this be ok?
public class MyPoco
{
private string _uriMapper;
public Uri SomeUri
{
get { return new Uri(_uriMapper); }
}
public string Mapper { set { _uriMapper = value; } }
}
Edit:
public class UriContainer
{
private string _uriMapper;
public string UriMapper { set { _uriMapper = value; } }
public int Id { get; set; }
public Uri SomeUri { get {return new Uri(_uriMapper);} }
}
public class DbTests
{
[Test]
public void Can_Get_A_Uri()
{
using (var c = new SqlConnection("hello"))
{
c.Open();
var uri = c.Query<UriContainer>("select *, someuri as urimapper from uris where id = 3").Single();
Console.WriteLine(uri.SomeUri);
}
}
}

App Engine JPA Datastore delete entity

im trying to build a google app engine projekt with JPA, JAX-RS and JAX-B. My POST and GET Methods work, but my DELETE method doesn't delete the data.
Resource
#DELETE
#Path("card/{id}")
public void deleteCardById (#PathParam ("id") Long id) {
Service.removeCard(id);
}
Service
public static void removeCard(Long id) {
EntityManager em = EMFService.get().createEntityManager();
Card emp = findCard(id);
if (emp != null) {
em.remove(emp);
}
em.close();
}
public static Card findCard(Long id) {
EntityManager em = EMFService.get().createEntityManager();
Card card = em.find(Card.class, id);
em.close();
return card;
}
Entity
#XmlRootElement
#Entity
public class Card {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
String begriff;
String tabu1;
String tabu2;
String tabu3;
public Card(String begriff, String tabu1, String tabu2, String tabu3) {
super();
Begriff = begriff;
Tabu1 = tabu1;
Tabu2 = tabu2;
Tabu3 = tabu3;
}
public Card() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getBegriff() {
return Begriff;
}
public void setBegriff(String begriff) {
Begriff = begriff;
}
public String getTabu1() {
return Tabu1;
}
public void setTabu1(String tabu1) {
Tabu1 = tabu1;
}
public String getTabu2() {
return Tabu2;
}
public void setTabu2(String tabu2) {
Tabu2 = tabu2;
}
public String getTabu3() {
return Tabu3;
}
public void setTabu3(String tabu3) {
Tabu3 = tabu3;
}
#Override
public String toString() {
return "Card [Begriff=" + Begriff + ", Tabu1=" + Tabu1 + ", Tabu2="
+ Tabu2 + ", Tabu3=" + Tabu3 + "]";
}
When i Debug the app it gives the correct Object to the remove function. But it just don't remove the data ...
You mean you're using v1 of the GAE JPA plugin, and you don't bother putting a transaction around your remove (so the remove is delayed until the next transaction ... which never happens)?
Obviously you could either put a transaction around the remove, or better still you use v2 of the GAE JPA plugin
I was facing similar issue too. the JPA delete actually deletes the entity in the datastore,but it doesn't delete the entity from the JPA Cache.. You page is actually using the JPA Cached result list to display..
The way I used to resolve the issue is to have the JPA Cache cleared every time after a delete.
Sample Code would be something like this:
EM.getTransaction().begin();
EM.remove(current_record);
EM.getTransaction().commit();
EM.getEntityManagerFactory().getCache().evictAll();
ok i think i should write it like this
*edit the problem was the findCard function, i think because of the secone instance of the EntityManager. I chnaged it without using this method to this and now it works.
public static void removeCard(Long id) {
EntityManager em = EMFService.get().createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
Card card = em.find(Card.class, id);
if (card != null) {
em.remove(card);
}
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
em.close();
}
}

Passing a list or array to RESTeasy using get

I've seen this kind of thing described in various examples showing how to create a REST service which takes arrays or a list of objects as part of the URL.
My question is, how to implement this using RESTeasy?
Something like the following would be how i would assume this to work.
#GET
#Path("/stuff/")
#Produces("application/json")
public StuffResponse getStuffByThings(
#QueryParam("things") List<Thing> things);
Create a StringConverter and a use a wrapper object. Here is a quick and dirty example:
public class QueryParamAsListTest {
public static class Thing {
String value;
Thing(String value){ this.value = value; }
}
public static class ManyThings {
List<Thing> things = new ArrayList<Thing>();
ManyThings(String values){
for(String value : values.split(",")){
things.add(new Thing(value));
}
}
}
static class Converter implements StringConverter<ManyThings> {
public ManyThings fromString(String str) {
return new ManyThings(str);
}
public String toString(ManyThings value) {
//TODO: implement
return value.toString();
}
}
#Path("/")
public static class Service {
#GET
#Path("/stuff/")
public int getStuffByThings(
#QueryParam("things") ManyThings things){
return things.things.size();
}
}
#Test
public void test() throws Exception {
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getProviderFactory().addStringConverter(new Converter());
dispatcher.getRegistry().addSingletonResource(new Service());
MockHttpRequest request = MockHttpRequest.get("/stuff?things=a,b,c");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
Assert.assertEquals("3", response.getContentAsString());
}
}
I think you can also use a StringParamUnmarshaller
I had some luck with this, using Collection rather than List. I was unable to make a StringConverter for List work.
#Provider
public class CollectionConverter implements StringConverter<Collection<String>> {
public Collection<String> fromString(String string) {
if (string == null) {
return Collections.emptyList();
}
return Arrays.asList(string.split(","));
}
public String toString(Collection<String> values) {
final StringBuilder sb = new StringBuilder();
boolean first = true;
for (String value : values) {
if (first) {
first = false;
} else {
sb.append(",");
}
sb.append(value);
}
return sb.toString();
}
}
I did the toString from my head. Be sure to write unit tests for it to verify. But of course, everything is easier and clearer when you use Guava. Can use Joiner and Splitter. Really handy.
Just use a wrapper on its own, no need for anything else.
In your endpoint
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#Path("/find")
#GET
MyResponse find(#QueryParam("ids") Wrapper ids);
And you wrapper looks like this :
public class Wrapper implements Serializable {
private List<BigInteger> ids = Collections.emptyList();
public String toString() {
return Joiner.on(",")
.join(ids);
}
public List<BigInteger> get() {
return ids;
}
public Wrapper(String s) {
if (s == null) {
ids = Collections.emptyList();
}
Iterable<String> splitted = Splitter.on(',')
.split(s);
Iterable<BigInteger> ids = Iterables.transform(splitted, Functionz.stringToBigInteger);
this.ids = Lists.newArrayList(ids);
}
public Wrapper(List<BigInteger> ids) {
this.ids = ids;
}
}

Resources