Android Unit Tests Requiring Context - database

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)

Related

Flink integration test(s) with Testcontainers

I have a simple Apache Flink job that looks very much like this:
public final class Application {
public static void main(final String... args) throws Exception {
final var env = StreamExecutionEnvironment.getExecutionEnvironment();
final var executionConfig = env.getConfig();
final var params = ParameterTool.fromArgs(args);
executionConfig.setGlobalJobParameters(params);
executionConfig.setParallelism(params.getInt("application.parallelism"));
final var source = KafkaSource.<CustomKafkaMessage>builder()
.setBootstrapServers(params.get("application.kafka.bootstrap-servers"))
.setGroupId(config.get("application.kafka.consumer.group-id"))
// .setStartingOffsets(OffsetsInitializer.committedOffsets(OffsetResetStrategy.EARLIEST))
.setStartingOffsets(OffsetsInitializer.earliest())
.setTopics(config.getString("application.kafka.listener.topics"))
.setValueOnlyDeserializer(new MessageDeserializationSchema())
.build();
env.fromSource(source, WatermarkStrategy.noWatermarks(), "custom.kafka-source")
.uid("custom.kafka-source")
.rebalance()
.flatMap(new CustomFlatMapFunction())
.uid("custom.flatmap-function")
.filter(new CustomFilterFunction())
.uid("custom.filter-function")
.addSink(new CustomDiscardSink()) // Will be a Kafka sink in the future
.uid("custom.discard-sink");
env.execute(config.get("application.job-name"));
}
}
Problem is that I would like to provide an integration test for the entire application — sort of like an end-to-end (set of) test(s) for the entire job. I'm using Testcontainers, but I'm not really sure how to move forward with this. For instance, this is how the test looks like (for now):
#Testcontainers
final class ApplicationTest {
private static final DockerImageName DOCKER_IMAGE = DockerImageName.parse("confluentinc/cp-kafka:7.0.1");
#Container
private static final KafkaContainer KAFKA_CONTAINER = new KafkaContainer(DOCKER_IMAGE);
#ClassRule // How come this work in JUnit Jupiter? :/
public static MiniClusterResource cluster;
#BeforeAll
static void init() {
KAFKA_CONTAINER.start();
// ...probably need to wait and create the topic(s) as well
final var config = new MiniClusterResourceConfiguration.Builder().setNumberSlotsPerTaskManager(2)
.setNumberTaskManagers(1)
.build();
cluster = new MiniClusterResource(config);
}
#Test
void main() throws Exception {
// new Application(); // ...what's next?
}
}
I'm not sure how to implement what's required to trigger the job as-is from that point on. Basically, I would like to execute what was defined before, without (almost) any modifications — I've seen plenty of examples that practically build the entire job again, so that's not an option.
Can somebody provide any pointers here?
MessageDeserializationSchema is unbounded, so isEndOfStream returns false. Not sure if that's an impediment.
In order to make the pipeline more testable, I suggest you create a method on your Application class that takes a source and a sink as parameters, and creates and executes the pipeline, using those connectors.
In your tests you can call that method with special sources and sinks that you use for testing. In particular, you will want to use a KafkaSource that uses .setBounded(...) in the tests so that it cleanly handles just the range of data intended for the test(s).
The solutions and tests for the Apache Flink training exercises are organized along these lines; for example, see RideCleansingSolution.java and RideCleansingIntegrationTest.java. These examples don't use kafka or test containers, but hopefully they'll still be helpful.
I would suggest you instrument your application as an opaque-box test by interacting with it through its public API. This can be done either as an out-process test (e.g. by running your application in a container as well, using Testcontainers) are as an in-process test (by creating your Application and calling its main() method).
Now in your comments you explained, that you want to check for the side-effects of interacting with your application (Kafka messages being published). To check this, connect to the KafkaContainer with your own KafkaConsumer from within the test and use a library such as Awaitiliy to wait until the messages have been received.

Static Analysis tool to catch self-invocation bypassing Spring cache #Cacheable method

I understand that this is because of the way proxies are created for handling caching, transaction related functionality in Spring. And the way to fix it is use AspectJ but I donot want to take that route cause it has its own problems. Can I detect self-invocation using any static analyis tools?
#Cacheable(value = "defaultCache", key = "#id")
public Person findPerson(int id) {
return getSession().getPerson(id);
}
public List<Person> findPersons(int[] ids) {
List<Person> list = new ArrayList<Person>();
for (int id : ids) {
list.add(findPerson(id));
}
return list;
}
If it would be sufficient for you to detect internal calls, you could use native AspectJ instead of Spring AOP for that and then throw runtime exceptions or log warnings every time this happens. That is not static analysis, but better than nothing. On the other hand, if you use native AspectJ, you are not limited to Spring proxies anyway and the aspects would work for self-invocation too.
Anyway, here is what an aspect would look like, including an MCVE showing how it works. I did it outside of Spring, which is why I am using a surrogate #Component annotation for demo purposes.
Update: Sorry for targeting #Component classes instead of #Cacheable classes/methods, but basically the same general approach I am showing here would work in your specific case, too, if you simply adjust the pointcut a bit.
Component annotation:
package de.scrum_master.app;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Retention(RUNTIME)
#Target(TYPE)
public #interface Component {}
Sample classes (components and non-components):
This component is to be called by other components should not lead to exceptions/warnings:
package de.scrum_master.app;
#Component
public class AnotherComponent {
public void doSomething() {
System.out.println("Doing something in another component");
}
}
This class is not a #Component, so the aspect should ignore self-invocation inside it:
package de.scrum_master.app;
public class NotAComponent {
public void doSomething() {
System.out.println("Doing something in non-component");
new AnotherComponent().doSomething();
internallyCalled("foo");
}
public int internallyCalled(String text ) {
return 11;
}
}
This class is a #Component. The aspect should flag internallyCalled("foo"), but not new AnotherComponent().doSomething().
package de.scrum_master.app;
#Component
public class AComponent {
public void doSomething() {
System.out.println("Doing something in component");
new AnotherComponent().doSomething();
internallyCalled("foo");
}
public int internallyCalled(String text ) {
return 11;
}
}
Driver application:
Please note that I am creating component instances throughout this sample code with new instead of requesting beans from the application context, like I would do in Spring. But you can ignore that, it is just an example.
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
new NotAComponent().doSomething();
new AComponent().doSomething();
}
}
Console log when running without aspect:
Doing something in non-component
Doing something in another component
Doing something in component
Doing something in another component
Now with the aspect, instead of the last message we would expect an exception or a logged warning. Here is how to do that:
Aspect:
Sorry for using native AspectJ syntax here. Of course, you could also use annotation-based syntax.
package de.scrum_master.aspect;
import de.scrum_master.app.*;
public aspect SelfInvocationInterceptor {
Object around(Object caller, Object callee) :
#within(Component) &&
call(* (#Component *).*(..)) &&
this(caller) &&
target(callee)
{
if (caller == callee)
throw new RuntimeException(
"Self-invocation in component detected from " + thisEnclosingJoinPointStaticPart.getSignature() +
" to "+ thisJoinPointStaticPart.getSignature()
);
return proceed(caller, callee);
}
}
Console log when running with aspect:
Doing something in non-component
Doing something in another component
Doing something in component
Doing something in another component
Exception in thread "main" java.lang.RuntimeException: Self-invocation in component detected from void de.scrum_master.app.AComponent.doSomething() to int de.scrum_master.app.AComponent.internallyCalled(String)
at de.scrum_master.app.AComponent.internallyCalled_aroundBody3$advice(AComponent.java:8)
at de.scrum_master.app.AComponent.doSomething(AComponent.java:8)
at de.scrum_master.app.Application.main(Application.java:6)
I think, you can use this solution and maybe rather log warnings instead of throwing exceptions in order to softly guide your co-workers to inspect and improve their AOP-dependent Spring components. Sometimes maybe they do not wish self-invocation to trigger an aspect anyway, it depends on the situation. You could run the Spring application in full AspectJ mode and then, after evaluating the logs, switch back to Spring AOP. But maybe it would be simpler to just use native AspectJ to begin with and avoid the self-invocation problem altogether.
Update: In AspectJ you can also make the compiler throw warnings or errors if certain conditions are met. In this case you could only statically determine calls from components to other components, but without differentiating between self-invocation and calls on other methods from other components. So this does not help you here.
Please also notice that this solution is limited to classes annotated by #Component. If your Spring bean is instantiated in other ways, e.g. via XML configuration or #Bean factory method, this simple aspect does not work. But it could easily be extended by checking if the intercepted class is a proxy instance and only then decide to flag self-invocations. Then unfortunately, you would have to weave the aspect code into all of your application classes because the check can only happen during runtime.
I could explain many more things, such as using self-injection and call internal methods on the injected proxy instance instead of via this.internallyCalled(..). Then the self-invocation problem would be solved too and this approach also works in Spring AOP.
Can I detect self-invocation using any static analysis tools?
In theory you can, but be aware of Rice's theorem. Any such tool would sometimes give false alarms.
You could develop such a tool using abstract interpretation techniques. You may need more than a year of work.
You could subcontract the development of such tools to e.g. the Frama-C team. Then email me to basile.starynkevitch#cea.fr

serenity-bdd with cucumber feature hooks

I am using Serenity-BDD with cucumber and I would like to run certain things only once per feature file. It looks like cucumber doesn't support this at the moment. I was wondering if serenity has some workaround for this.
I've also tried to use the JUnit #BeforeClass, #AfterClass hooks in the test suite class but the 2 annotations require static methods and I cannot access the serenity page objects methods at that time (there is no instance injected at that point in time).
You could try setting up a static global flag which will make sure that the before method will runs only once.
Setup the feature file with a tag.
#RunOnce
Feature: Run Once
Use the following hook in your stepdefinition.
private static boolean onceFlag = true;
#Before(value="#RunOnce")
public void beforeOnce(){
if(onceFlag) {
onceFlag = false;
//Your code to write once per feature file
}
}
You could try to implement net.thucydides.core.steps.StepListener interface and connect it via SPI. I described this in answer in this post

Calling data from one class to another class - framework for JUnit

Please forgive me as I am still very new to the world of test automation. I have started out by using Selenium WebDriver with JUnit4, predominately on windows OS, although I have modified my scripts and ran them on Mac.
I want to be able to create a set of classes containing set data such as usernames, passwords, default url . Perhaps even calling them from an excel file, but for now Im happy to store the data in classes and then pass that data into other test classes. Im guessing this would be a framework of some sort.
Currently I am writing classes that all begin with something like:
public class ExampleSQATest{
public static Chromedriver chrome;
#BeforeClass
public static void launchBrowser(){
System.setProperty("webdriver.chrome.driver", "chromedriver/chromedriver.exe");
chrome = new ChromeDrievr();
}
#Test
public void aLogin(){
chrome.manage().window().maximize();
chrome.navigate().to("http://mydummywebsite.com");
new WebDriverWait(chrome, 10).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector
("input#UserName")));
WebElement username = chrome.findElementByCssSelector("input#UserName");
username.sendKeys("username");
WebElement password = chrome.findElementByCssSelector("input#Password");
password.sendKeys("password");
WebElement submit = chrome.findElementByCssSelector("input[type='submit']");
submit.click();
}
}
I will then proceed to write further test methods which requires entering data, but I'd like to be able to call this data from somewhere else that is already predefined.
Can anyone provide any suitable suggestions to investigate so I can learn. Something that is a guide or tutorial. Nothing too advanced, just something that helps me get started by advising me how to set a class of methods to be called by other classes and how it all links together as a framework.
Many thanks in advance.
One way to do this
public abstract class TestBase
{
private readonly INavigationManager navMgr;
private readonly IWindowNavigator windowNav;
private readonly ILoginManager loginMgr;
// All your stuff that is common for all the tests
protected TestBase()
{
this.navMgr = WebDriverManager.Get<INavigationManager>();
this.windowNav = WebDriverManager.Get<IWindowNavigator>();
this.loginMgr = WebDriverManager.Get<ILoginManager>();
}}
[TestFixture]
internal class QueriesTest : TestBase
{
private QueryTests queryTests;
[SetUp]
public void Setup()
{
this.queryTests = WebDriverManager.Get<QueryTests>();
// all the stuff you run specific before tests in this test class.
}
}
Assuming you have created test classes in webdriver-junit4, Use following two classes to call your test classes (Note-Import junit annotations)
1)Create test suite class as -
#RunWith(Suite.class)
#Suite.SuiteClasses({
YourTestClass1.class,
YourTestClass2.class,[you can add more tests you have created...]
})
public class TestSuiteJU {
}
2)Create class to call suite created above as-
public class TestExecution {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(TestSuiteJU .class);
}
}

Log4Net in App object?

I am getting started with Logging in a WPF desktop app, using Log4Net as the logging component. Here is my question: In a simple desktop app, is there any reason not to instantiate my logger as a property ov the App class (App.xaml.cs), like this?
public partial class App : Application
{
private static readonly ILog p_Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public ILog Logger
{
get { return p_Logger; }
}
#endregion
}
}
That would allow me to invoke the logger
One reason springs to mind: since the App class's static constructor is the first bit of your code that will run, you will be instantiating the ILog instance before you've configured log4net. Therefore, you ILog instance won't be usable. Generally, you would instead do something like this:
public partial class App : Application
{
private static ILog log;
static App()
{
XmlConfigurator.Configure();
log = LogManager.GetLogger(typeof(App));
}
}
BTW, that MethodBase business really makes me cringe. Why not just use typeof(App)? You shouldn't be copy/pasting code without verifying it, anyway...and typeof(App) will work just fine with refactoring tools...
A couple of cases against using one global instance. By using one logger per class you get:
the benefit of logger hierarchies automatically following your class structure.
lesser coupling (your classes no longer have a dependency on the App class).
I did find a reason not to use a global logger in the App object. It works fine, but there is an advantage to getting a logger from within each class that will use it--It makes my log messages shorter and easier to write.
So I call GetLogger() in each class that will log, and I specify the name to be used for the logger. For example, in my OpenFile method, I can get a logger like this:
// Get logger
var logger = LogManager.GetLogger("OpenFile");
That relieves me of entering the class name in every error message I write. I still configure log4net in the App() constructor, since that only needs to be done once. That gives me a log message that looks like this:
2010-03-29 15:51:41,951 OpenFile [DEBUG]- Data file opened.
Kent's answer is still the accepted answer, but I figured I'd pass along what I had learned.

Resources