Mocking a method inside my test class - mockito

Android Studio 2.3
I have the following method I want to test inside my model class:
public class RecipeListModelImp implements RecipeListModelContract {
private Subscription subscription;
private RecipesAPI recipesAPI;
private RecipeSchedulers recipeSchedulers;
#Inject
public RecipeListModelImp(#NonNull RecipesAPI recipesAPI, #NonNull RecipeSchedulers recipeSchedulers) {
this.recipesAPI = Preconditions.checkNotNull(recipesAPI);
this.recipeSchedulers = Preconditions.checkNotNull(recipeSchedulers);
}
#Override
public void getRecipesFromAPI(final RecipeGetAllListener recipeGetAllListener) {
subscription = recipesAPI.getAllRecipes()
.subscribeOn(recipeSchedulers.getBackgroundScheduler())
.observeOn(recipeSchedulers.getUIScheduler())
.subscribe(new Subscriber<List<Recipe>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
recipeGetAllListener.onRecipeGetAllFailure(e.getMessage());
}
#Override
public void onNext(List<Recipe> recipe) {
recipeGetAllListener.onRecipeGetAllSuccess(recipe);
}
});
}
#Override
public void shutdown() {
if(subscription != null && !subscription.isUnsubscribed()) {
subscription.unsubscribe();
}
}
}
Inside my test class I am testing like this:
public class RecipeListModelImpTest {
#Mock Subscription subscription;
#Mock RecipesAPI recipesAPI;
#Mock RecipeListModelContract.RecipeGetAllListener recipeGetAllListener;
#Mock List<Recipe> recipes;
#Inject RecipeSchedulers recipeSchedulers;
private RecipeListModelContract recipeListModel;
#Before
public void setup() {
TestBusbyComponent testBusbyComponent = DaggerTestBusbyComponent.builder()
.mockRecipeSchedulersModule(new MockRecipeSchedulersModule())
.build();
testBusbyComponent.inject(RecipeListModelImpTest.this);
MockitoAnnotations.initMocks(RecipeListModelImpTest.this);
recipeListModel = new RecipeListModelImp(recipesAPI, recipeSchedulers);
}
#Test(expected = NullPointerException.class)
public void testShouldThrowExceptionOnNullParameter() {
recipeListModel = new RecipeListModelImp(null, null);
}
#Test
public void testRecipeListModelShouldNotBeNull() {
assertNotNull(recipeListModel);
}
#Test
public void testShouldGetRecipesFromAPI() {
when(recipesAPI.getAllRecipes()).thenReturn(Observable.just(recipes));
recipeListModel.getRecipesFromAPI(recipeGetAllListener);
verify(recipesAPI, times(1)).getAllRecipes();
verify(recipeGetAllListener, times(1)).onRecipeGetAllSuccess(recipes);
verify(recipeGetAllListener, never()).onRecipeGetAllFailure(anyString());
}
#Test
public void testShouldFailToGetRecipesFromAPI() {
when(recipesAPI.getAllRecipes())
.thenReturn(Observable.<List<Recipe>>error(
new Throwable(new RuntimeException("Failed to get recipes"))));
recipeListModel.getRecipesFromAPI(recipeGetAllListener);
verify(recipesAPI, times(1)).getAllRecipes();
verify(recipeGetAllListener, times(1)).onRecipeGetAllFailure(anyString());
verify(recipeGetAllListener, never()).onRecipeGetAllSuccess(recipes);
}
#Test
public void testShouldShutdown() {
when(subscription.isUnsubscribed()).thenReturn(false);
final Field subscriptionField;
try {
subscriptionField = recipeListModel.getClass().getDeclaredField("subscription");
subscriptionField.setAccessible(true);
subscriptionField.set(recipeListModel, subscription);
} catch(NoSuchFieldException e) {
e.printStackTrace();
}
catch(IllegalAccessException e) {
e.printStackTrace();
}
recipeListModel.shutdown();
verify(subscription, times(1)).unsubscribe();
}
}
However, the problem is the Subscription in my model class is always null so will never enter the if blook. Is there any way to test this with using Mockito or spys?
Many thanks for any suggestions,

You should for testing recipeListModel class, where you have shutdown() method , set mock into this class.
If you don't have set method for subscription in recipeListModel , or constructor param.... ),you can set mock object with reflection like :
#Test
public void testShouldShutdown() {
Subscription subscription = mock(Subscription.class);
when(subscription.isUnsubscribed()).thenReturn(false);
Field subscriptionField = recipeListModel.getClass().getDeclaredField("subscription");
subscriptionField.setAccessible(true);
subscriptionField.set(recipeListModel, subscriptionMock);
recipeListModel.shutdown();
verify(subscription, times(1)).unsubscribe();
}
after your update :
if you can't change way of creation , you should mock it like (full way of creation) , i don't know your api , so it's just idea:
Subscription subscription = mock(Subscription.class);
when(subscription.isUnsubscribed()).thenReturn(false);
// preparation mock for create Subscription
//for recipesAPI.getAllRecipes()
Object mockFor_getAllRecipes = mock(....);
when(recipesAPI.getAllRecipes()).thenReturn(mockFor_getAllRecipes );
//for subscribeOn(recipeSchedulers.getBackgroundScheduler())
Object mockFor_subscribeOn = mock();
when(mockFor_getAllRecipes.subscribeOn(any())).thenReturn(mockFor_subscribeOn);
//for .observeOn(recipeSchedulers.getUIScheduler())
Object mockFor_observeOn = mock();
when(mockFor_subscribeOn .observeOn(any())).thenReturn(observeOn);
// for .subscribe
when(observeOn.subscribe(any()).thenReturn(subscription);

Related

How to use the mock object of the test class and call main method from the test class

In the test class trying to test the main method and not sure how to use the mock object here.
How to use the mock object orders to call the main method and it's methods inside the main method
Any suggestions on how this can be done?
public class Orders {
public static void main(String[] s) {
Orders jp = new Orders();
jp.method1();
List<OrderItems> lstOrdItms = jp.getListOrderItems();
jp.processOrderItems( lstOrdItms );
}
public void method1(List<OrderItem> lstOrderItem) {
.........
}
public List<OrderItem> getListOrderItems() {
............
}
public void processOrderItems() {
............
}
}
public class OrdersTest {
#Mocks
Orders orders;
.....
#Before
public void setUp() {
........
}
#Test
public void testMain() throws SQLException {
// Not sure how to test here
// This will actually execute the main method instead of mock.
orders.main(new String[]{});
}
}

How to add AdMob Interstitial banner to LibGDX game with several activities and classes?

I have a game on LibGDX. According to this
http://www.norakomi.com/tutorial_admob_part2_banner_ads1.php
instruction I created necessery methods in AndroidLauncher.java file. And in the core file, generated by AndroidLauncher.java, I have created the controller and also interface java file
( http://www.norakomi.com/tutorial_admob_part2_banner_ads2.php ).
The problem is that my game has several classes which extend one another and the corresponding condition, which I want to use for displaying adMob, is not that one to which method "initialize" gives "this" from AndroidLauncher.java file. But to download and to give request for adMob is possible only from AndroidLauncher.java, because another classes are in its own game view.
How to solve this?
This is the basic code from AndroidLauncher.java
public class AndroidLauncher extends AndroidApplication implements AdsController {
private static final String BANNER_AD_UNIT_ID = "ca-app-pub-3940256099942544/6300978111";
private static final String INTERSTITIAL_AD_UNIT_ID = "ca-app-pub-3940256099942544/1033173712";
AdView bannerAd;
InterstitialAd interstitialAd;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
// Create a gameView and a bannerAd AdView
View gameView = initializeForView(new Stork2016(this), config);
setupBanner();
setupInterstitial();
// Define the layout
RelativeLayout layout = new RelativeLayout(this);
layout.addView(gameView, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
layout.addView(bannerAd, params);
setContentView(layout);
config.useCompass = false;
config.useAccelerometer = false;
public void setupBanner() {
bannerAd = new AdView(this);
//bannerAd.setVisibility(View.VISIBLE);
//bannerAd.setBackgroundColor(0xff000000); // black
bannerAd.setAdUnitId(BANNER_AD_UNIT_ID);
bannerAd.setAdSize(AdSize.SMART_BANNER);
}
public void setupInterstitial() {
interstitialAd = new InterstitialAd(this);
interstitialAd.setAdUnitId(INTERSTITIAL_AD_UNIT_ID);
AdRequest.Builder builder = new AdRequest.Builder();
AdRequest ad = builder.build();
interstitialAd.loadAd(ad);
#Override
public void showInterstitialAd(final Runnable then) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (then != null) {
interstitialAd.setAdListener(new AdListener() {
#Override
public void onAdClosed() {
Gdx.app.postRunnable(then);
AdRequest.Builder builder = new AdRequest.Builder();
AdRequest ad = builder.build();
interstitialAd.loadAd(ad);
}
});
}
interstitialAd.show();
}
});
}
#Override
public boolean isWifiConnected() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return (ni != null && ni.isConnected());
}
#Override
public void showBannerAd() {
runOnUiThread(new Runnable() {
#Override
public void run() {
bannerAd.setVisibility(View.VISIBLE);
AdRequest.Builder builder = new AdRequest.Builder();
AdRequest ad = builder.build();
bannerAd.loadAd(ad);
}
});
}
#Override
public void hideBannerAd() {
runOnUiThread(new Runnable() {
#Override
public void run() {
bannerAd.setVisibility(View.INVISIBLE);
}
});
}
}
And then we have file Stork2016.java in which we create AdsController to be able to use methods for adds in AndroidLauncher.java.
private AdsController adsController;
public Stork2016(AdsController adsController){
this.adsController = adsController;
}
#Override
public void create () {
adsController.showBannerAd();
batch = new SpriteBatch();
gsm = new GameStateManager();
music = Gdx.audio.newMusic(Gdx.files.internal("music.mp3"));
music.setLooping(true);
music.setVolume(0.5f);
music.play();
Gdx.gl.glClearColor(1, 0, 0, 1);
gsm.push(new MenuState(gsm));
}
And also we have interface java file AdsController.java
public interface AdsController {
public void showBannerAd();
public void hideBannerAd();
public void showInterstitialAd (Runnable then);
public boolean isWifiConnected();
}
So, as we can see in Stork2016 we have "gsm.push(new MenuState(gsm));" and in MenuState.java I have "gsm.set(new PlayState(gsm));". In PlayState.java there is the part of code:
#Override
public void update(float dt) {
handleInput();
updateGround();
....
if (tube.collides(bird.getBounds()))
gsm.set(new GameOver(gsm));
...
}
}
camera.update();
}
The condition "if" frome the above code I want to use to show interstitial adMob. But it is impossibe, because the contoller which takes methods from AndroidLauncher.java can be created only in Stork2016.java. And also in AndroidLauncher.java there is
View gameView = initializeForView(new Stork2016(this), config);
wich transfers "this" to Stork2016, where is the controller.
In my AndroidLauncher activity I start the game and initialize the Insterstitial ad. Then I initialize my interface which I call from inside the game, to trigger show/hide of the interstitial ad.
For example I have method showInterstitialAd() in my interface listener, then my implementation on Android would be:
#Override
public void showCoverAd() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (interstitialAd.isLoaded()) {
interstitialAd.show();
}
}
});
}
And on iOS-MOE:
#Override
public void showCoverAd() {
if (gadInterstitial.isReady()) {
gadInterstitial.presentFromRootViewController(uiViewController);
}
}
So you need the make sure that the interface listener knows about the interstitial ad, for example AndroidLauncher implements MyGameEventListener
In my case interface AdsController.java is implemented in AndroidLauncher.java:
public class AndroidLauncher extends AndroidApplication implements AdsController { ...
And then by this part of code:
View gameView = initializeForView(new Stork2016(this), config);
we send "this" to new class Strork2016.java.
And in the class Stork2016.java I create constructor:
private AdsController adsController;
public Stork2016(AdsController adsController){
this.adsController = adsController;
}
which lets us use methods from interface AdsController.java.
But only in this class Stork2016. If I want to use it in another class:
gsm.push(new MenuState(gsm));
this is impossible and this is the problem.
OK guys, I have solved the problem.
I had to create two consturctors in both classes: the main core class which is initialyzed from AndroidLauncher and in the class GameStateManager. Because the class, where I want admob intersitital to be called, is created by method gsm.push which is described in class GameStateManager. Actually, in GameStateManager there have already been constuructor, so I hade only to add necessary code to this constructor.

#CacheEvict with key="#id" throws NullPointerException

I'm trying to use Spring Caching annotations #Cacheable and #CacheEvict together with the GuavaCacheManager.
I've created a test case with these two tests:
cachesById - verifies that two invocations to a method annotatted with #Cacheable returns the same object
evict - verifies that two different instances are returned if a method annotated with #CacheEvict is called in-between those two invocations
Both work fine when i don't specify a key for #CacheEvict, however when I do i get the following exception:
java.lang.NullPointerException
at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:210)
at com.google.common.cache.LocalCache$LocalManualCache.invalidate(LocalCache.java:4764)
at org.springframework.cache.guava.GuavaCache.evict(GuavaCache.java:135)
at org.springframework.cache.interceptor.AbstractCacheInvoker.doEvict(AbstractCacheInvoker.java:95)
at org.springframework.cache.interceptor.CacheAspectSupport.performCacheEvict(CacheAspectSupport.java:409)
at org.springframework.cache.interceptor.CacheAspectSupport.processCacheEvicts(CacheAspectSupport.java:392)
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:362)
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:299)
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at com.myorg.caching.CacheTest$Repo$$EnhancerBySpringCGLIB$$eed50f3e.update(<generated>)
at com.myorg.caching.CacheTest.evict(CacheTest.java:50)
This can be reproduced by executing the below test.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(
classes = { Repo.class, CacheTest.SpringConfig.class },
loader = AnnotationConfigContextLoader.class)
public class CacheTest {
private static final String CACHE_NAME = "cacheName";
#Inject
private Repo repo;
#Test
public void cachesById() {
Entity aResult1 = repo.getEntity(1);
Entity aResult2 = repo.getEntity(1);
assertEquals(aResult1.getId(), aResult2.getId());
assertSame(aResult1, aResult2);
}
#Test
public void evict() {
Entity aResult1 = repo.getEntity(1);
repo.update(aResult1);
Entity aResult2 = repo.getEntity(1);
assertEquals(aResult1.getId(), aResult2.getId());
assertNotSame(aResult1, aResult2);
}
/** Mock repository/entity classes below. */
#Component
public static class Repo {
#Cacheable(value = CACHE_NAME, key = "#id")
public Entity getEntity(int id) {
return new Entity(id);
}
#CacheEvict(value = CACHE_NAME, key = "#id")
public void update(Entity e) {
}
}
public static class Entity {
private int id;
public Entity(int id) {
super();
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
/** Guava Cachemanager Spring configuration */
#Configuration
#EnableCaching
public static class SpringConfig {
#Bean
public CacheManager cacheManager() {
GuavaCacheManager manager = new GuavaCacheManager(CACHE_NAME);
manager.setCacheBuilder(CacheBuilder.newBuilder().expireAfterWrite(
1, TimeUnit.MINUTES).recordStats());
return manager;
}
}
}
However the test passes if I change
#CacheEvict(value = CACHE_NAME, key = "#id")
public void update(Entity e) {
into:
#CacheEvict(value = CACHE_NAME)
public void update(Entity e) {
..but then I'm missing the point where I need to specify the cache key for Entity. Does anyone know what I'm missing?
Thanks!
You have to fix you component class from
#Component
public static class Repo {
#Cacheable(value = CACHE_NAME, key = "#id")
public Entity getEntity(int id) {
return new Entity(id);
}
#CacheEvict(value = CACHE_NAME, key = "#id")
public void update(Entity e) {
}
}
to
#Component
public static class Repo {
#Cacheable(value = CACHE_NAME, key = "#id")
public Entity getEntity(int id) {
return new Entity(id);
}
#CacheEvict(value = CACHE_NAME, key = "#e?.id")
public void update(Entity e) {
}
}
Why? In getEntity method you're caching an Entity object using int id, you have to pass the same int id into the #CacheEvict annotated method. You don't have to change method's signature - by using SPEL you can "get into" entity and use its id field.
Hope I helped.

Ninject summon graphs with argument

Here is my problem. I have a presenter class, lets call it 'Presenter' that takes an IDataSource as a constructor argument. There are different implementations of the IDataSource interface. I would like to be able to pass some argument to Ninject and based on that argument one of several IDataSource implementations should by used. I've provided some sample code below. I think that my solution is really ugly and that there must be a smarter, cleaner way to do this. How are you guys solving this type of problem?
Here is my sample code
public class Presenter
{
public Presenter(IDataSource dataSource)
{
DataSource = dataSource;
}
private IDataSource DataSource { get; set; }
public List<string> GetData()
{
return DataSource.GetAll();
}
}
public class InMemoryDataSource : IDataSource
{
public List<string> GetAll()
{
return new List<string> {"a", "b"};
}
}
public class DbDataSource : IDataSource
{
public List<string> GetAll()
{
return new List<string> { "1", "2" };
}
}
public interface IDataSource
{
List<string> GetAll();
}
public class Module : NinjectModule
{
public override void Load()
{
Bind<Presenter>().To<Presenter>().Named("Db");
Bind<Presenter>().To<Presenter>().Named("InMemory");
Bind<IDataSource>().To<InMemoryDataSource> ().WhenParentNamed("InMemory");
Bind<IDataSource>().To<DbDataSource>().WhenParentNamed("Db");
}
}
[Test]
public void Run()
{
using (var kernel = new StandardKernel(new Module()))
{
var p = kernel.Get<Presenter>(x => x.Name == "InMemory");
foreach(var s in p.GetData())
{
Console.Out.WriteLine(s);
}
}
}
This depends on what you want to do. I assume that you want to use a different db for testing than for production. In this case would create the module with the production configuration in mind and simply Rebind everything for testing:
public class Presenter
{
public Presenter(IDataSource dataSource)
{
DataSource = dataSource;
}
private IDataSource DataSource { get; set; }
public List<string> GetData()
{
return DataSource.GetAll();
}
}
public class InMemoryDataSource : IDataSource
{
public List<string> GetAll()
{
return new List<string> {"a", "b"};
}
}
public class DbDataSource : IDataSource
{
public List<string> GetAll()
{
return new List<string> { "1", "2" };
}
}
public interface IDataSource
{
List<string> GetAll();
}
public class Module : NinjectModule
{
public override void Load()
{
Bind<Presenter>().To<Presenter>();
Bind<IDataSource>().To<DbDataSource>();
}
}
[Test]
public void Run()
{
using (var kernel = new StandardKernel(new Module()))
{
kernel.Rebind<IDataSource>().To<InMemoryDataSource>();
var p = kernel.Get<Presenter>();
foreach(var s in p.GetData())
{
Console.Out.WriteLine(s);
}
}
}

Ninject, passing constructor argument to the kernel

Here is my problem:
I want to pass in one of the values to the constructor every time I request an instance form the kernel. I written some code below to illustrate the problem. The test is not failing so I guess that this works, but it does look pretty ugly. Is there a better, cleaner way to accomplish this with Ninject? Or should I rethink my design? All suggestions are appreciated.
[TestFixture]
public class Sandbox
{
[Test]
public void Run_Forrest_Run()
{
using (var kernel = new StandardKernel(new Module()))
{
var connection = new Connection(Guid.NewGuid().ToString());
var downloader = kernel.Get<IDownloader>(new IParameter[] { new Parameter("connection", connection, false) });
Assert.That(downloader.Connection.Info, Is.EqualTo(connection.Info));
}
}
public class Downloader : IDownloader
{
public Downloader(Connection connection, ILogger logger)
{
Connection = connection;
Logger = logger;
}
public Connection Connection { get; private set; }
public void Download()
{
Logger.Log("Downloading...");
}
public ILogger Logger { get; private set; }
}
public interface IDownloader
{
Connection Connection { get; }
void Download();
}
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.Out.WriteLine(message);
}
}
public interface ILogger
{
void Log(string message);
}
public class Connection
{
public Connection(string info)
{
Info = info;
}
public string Info { get; private set; }
}
public class Module : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<ConsoleLogger>();
Bind<IDownloader>().To<Downloader>()
.WithConstructorArgument("connection", context =>
{
var p = context.Parameters.First(x => x.Name == "connection");
return p.GetValue(context, null);
});
}
}
}
If you always want to specify the Connection when resolving a IDownloader then I think the ConstructorArgument (which is a IParameter) is what you are looking for:
[Test]
public void Run_Forrest_Run()
{
using (var kernel = new StandardKernel(new Module()))
{
var connection = new Connection(Guid.NewGuid().ToString());
var downloader = kernel.Get<IDownloader>(new [] {
new ConstructorArgument("connection", connection) });
Assert.That(downloader.Connection.Info, Is.EqualTo(connection.Info));
}
}
public class Module : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<ConsoleLogger>();
Bind<IDownloader>().To<Downloader>();
}
}

Resources