Why "getSharedPreferences" return null in unit testing? - unit-testing

My classes is written in Kotlin and here is my SharedPreferenceHandler
class SharedPreferenceHandler(sharedPrefs: SharedPreferences) {
companion object {
var mInstance: SharedPreferenceHandler = SharedPreferenceHandler(getPrefs())
private fun getPrefs(): SharedPreferences {
return Application.mInstance.getSharedPreferences(
"myApp", Context.MODE_PRIVATE)
}
fun getInstance(): SharedPreferenceHandler {
return mInstance
}
}
private var sharedPreferences = sharedPrefs
var accessToken: String?
get() = sharedPreferences.getString(SharedPreference.ACCESS_TOKEN.name, null)
set(token) = sharedPreferences.edit().putString(SharedPreference.ACCESS_TOKEN.name, token).apply()
}
Here is method called in presenter:
override fun reload(vm: ViewModel) {
super.updateViewModel(vm) {
//some stuffs
}
}
Here is my test method:
#Test
public void reload() {
when(SharedPreferenceHandler.Companion.getMInstance().getAccessToken()).thenReturn("234234234234234");
presenter.reload(viewModel);
}
In handler from super.updateViewModel(vm) I call "SharedPreferenceHandler.mInstance.accessToken!!)"
That is what is thrown:
Caused by: java.lang.IllegalStateException:
Application.mInstanc…m", Context.MODE_PRIVATE) must not be null
at
com.zuum.zuumapp.preferences.SharedPreferenceHandler$Companion.getPrefs(SharedPreferenceHandler.kt:18)
at
com.zuum.zuumapp.preferences.SharedPreferenceHandler$Companion.access$getPrefs(SharedPreferenceHandler.kt:14)
at
com.zuum.zuumapp.preferences.SharedPreferenceHandler.(SharedPreferenceHandler.kt:15)
I wanna to get accessToken by calling " SharedPreferenceHandler.mInstance.accessToken!!" in my test class.
Is possible to get that in my test method?

You can't use Android SharedPreferences in unit test, but you can mock your method call by this:
Mockito.`when`(SharedPreferenceHandler.mInstance.accessToken).thenReturn("token")
And return what you need.

You should not test your code this way. You should create an interface for class you want to mock:
interface MySharedPreferences {
fun getAccessToken(): String
}
Let your SharedPreferencesHandler implements this interface. Then in your presenter (or other class you want to test) inject dependencies (f.e. by constructor or framework like Dagger/Kodein) into your object. Then there is possibility to easy mock this interface. I assume in #Before you create class you test - and then just pass as param your mocked SharedPreferencesHandler.
Testing things with static dependencies is possible, but is but tricky (and a lot of people consider static dependencies as anti-pattern). How to do it is described here: How to android unit test and mock a static method
Example:
class MyPresenter(val sp: MySharedPreferences) {
/* some code here */
fun validateToken() {
if (sp.getAccessToken() == "") throw new Exception()
}
}
Like you see sp is injected into this class as parameter. Normally you don't create views/presenters etc. directly in code but by DI framework (like Dagger or Kodein). Anyway, static dependencies are not easy testable. Injected interface-dependencies can be mocked, and you operating not on object, but on behaviors (so it's bigger level of abstraction). So, now in your test all you have to do is:
class MyTest() {
#Mock lateinit var sharedPreferencesMock: MySharedPreferences
lateinit var instance: MyPresenter
#Before
fun setUp() {
instance = MyPresenter(sharedPreferencesMock)
}
#Test
fun testSomething() {
`when`(sharedPreferencesMock.getAccessToken()).thenReturn("myAccessToken")
/* here is your test body */
}
}

Related

Not able to mock private methods using POWERMOCK and mockito

even when I am using the spy method, I am not able to mock the getContext() method of attributesStorage() to get my context.
this is my code :
class Rich
{
fun method1() : HashMap<String,String>
{
val x = attributeStorage().getStore()
return x
}
}
class AttributeStorage
{
private fun getContext()
{
return MyProject.instance.context()
}
fun getStore()
{
//some work done,
return HashMap<String,String>()
}
}
#PrepareForTest(Rich::class)
class RichTest {
#Mock
lateinit var mcontext: Context
fun init()
{
mcontext = Mockito.mock(Context::class.java)
val mAttributesStorage = spy(AttributesStorage())
`when`<Context>(mAttributesStorage,"getContext").thenReturn(mcontext)
Mockito.`when`(mAttributesStorage.getStore()).thenReturn(mapOf("1" to "1"))
}
fun test()
{
//gives an error because the getContext() couldn't be mocked
}
}
I looked at every question possible on stack overflow and went through powermock and mockito documentation but couldn't find a solution to this.
#Mock
lateinit var mcontext: Context
and
mcontext = Mockito.mock(Context::class.java)
are one too many. Use either the one or the other (annotation preferred, of course).
See Shorthand for mocks creation - #Mock annotation:
Important! This needs to be somewhere in the base class or a test runner:
MockitoAnnotations.initMocks(testClass);
Regarding your last code comment: objects are mocked, methods are stubbed.

How to Implement Unit test on my retrofit2 presenter using mockito?

i want to make a unit testing by using mockito dependencies on my code. it is always failed because view.processMatchData(data) and view.hideLoading() are in closure part in this presenter code, so that unit test will not detect them. Please, somebody help me solve this problem.
open class MatchSearchPresenter(
private val view: MatchSearchView,
private val apiService: ApiService,
private val cari : String
) {
fun searchMatch() {
view.showLoading()
apiService.loadSearchMatch(cari).enqueue(object : Callback<MatchSearchResponseModel> {
override fun onResponse(call: Call<MatchSearchResponseModel>, response: Response<MatchSearchResponseModel>)
{
if (response.isSuccessful) {
val data = response.body()!!
view.processMatchData(data)
}
view.hideLoading()
}
override fun onFailure(call: Call<MatchSearchResponseModel>, error: Throwable)
{
Log.e("Error", error.message)
view.hideLoading()
}
})
}
}
here are my unit test :
class MatchSearchPresenterTest {
#Mock
private lateinit var view: MatchSearchView
#Mock
private lateinit var apiService: ApiService
#Mock
private lateinit var teamPresenter: MatchSearchPresenter
#Mock
private lateinit var call: Call<MatchSearchResponseModel>
#Mock
private lateinit var something: Callback<MatchSearchResponseModel>
#Before
fun setUp() {
MockitoAnnotations.initMocks(this)
val kata = "Man United"
teamPresenter = MatchSearchPresenter(view, apiService, kata )
}
#Test
fun searchMatch() {
val teamId = "Man United"
val teams: MutableList<PrevMatchData> = mutableListOf()
val data = MatchSearchResponseModel(teams)
teamPresenter.searchMatch()
argumentCaptor<MatchSearchView>().apply {
Mockito.verify(apiService.loadSearchMatch(teamId).enqueue(something))
firstValue.processMatchData(data)
firstValue.hideLoading()
}
Mockito.verify(view).showLoading()
Mockito.verify(view).processMatchData(data)
Mockito.verify(view).hideLoading()
}
}
but this is not working by showing message like this :
java.lang.NullPointerException
at com.example.footballleaguecataloguefourth.ui_bottom_navigation.schedule.match_search.MatchSearchPresenter.searchMatch(MatchSearchPresenter.kt:19)
at com.example.footballleaguecataloguefourth.ui_bottom_navigation.schedule.match_search.MatchSearchPresenterTest.searchMatch(MatchSearchPresenterTest.kt:41)
I think what you want here is to have the call returned by ApiService call the correct method as soon as it's enqueued.
To do this you can use Mockito's thenAnswer - Here's an example. In your case, you can try this:
Mockito.`when`(call.enqueue(Mockito.any())).thenAnswer {
(it.getArgument(0) as Callback<MatchSearchResponseModel>).onResponse(
call,
Response.success(MatchSearchResponseModel(/*whatever is needed to build this object*/))
)
}
Here, you make sure that once call.enqueue is called with any argument, it'll immediately call the onResponse method with a success reponse. You can do something similar for an error and you can also call onFailure.
The last thing you need to do is to make sure that your api service returns the configured mocked call:
Mockito.`when`(apiService.loadSearchMatch(kata)).thenReturn(call)
I'd put this per test. So before you call your presenter method, I'd configure the mocks like this.
Now, calling teamPresenter.searchMatch(), should call apiService.loadSearchMatch(cari), which will return the mocked call that once enqueued will call the passed callback's onResponse method.
Lastly, as you might have noticed when is actually written with backticks. This is because it's a kotlin keyword that needs to be escaped. Not only for this reason but many more, you could consider using Mockito Kotlin which is a superb kotlin library wrapping mockito and makes life much easier.

mockito InjectMocks not working?

I am trying to use a test implementation of a class and using that to be injected to the test using #InjectMocks but it doesn't seem to inject it. I tried using Spy but that did not work and instead created a blank mocked version instead of using the version I created inside my #Before function
Here is my test code below:
#Before
fun setup() {
someFunction = object : SomeFuntionContract {
override fun save(test: String) {
testData = test //breakpoint here but never executes
}
override fun get(): String {
return testData
}
}
}
lateinit var testData : String
#InjectMocks
lateinit var delegator: Delegator
#Spy
lateinit var someFunction: SomeFunctionContract
#Test
fun testSomething{
delegator.retrieve(something)
Assert.assertTrue(someFunction.get() == "hello")
}
SomeFunctionContract.kt is an interface that has save and get functions and SomeFunction is the real implementation test
Inside delegator.retrieve it calls someFunction.get inside it and I am trying to see if it gets called and saves the data.
Make sure you init the creation and injection of the mocks by:
1) Adding #RunWith(org.mockito.junit.MockitoJUnitRunner) on the test class.
or
2) Adding MockitoAnnotations.initMocks(this) to your #Before method.
The #Before method is called after Mockito does its injection magic so, you are overwriting the spy created and used by Mockito. If you want to have your own implementation of the object to be injected (I'm assuming it is SomeFunctionContract) then you have to declare it on the property instead of on the #Before function.
All that said, I think we are missing some context of your code. Can you attach the code for something, Delegator and testData?
Fixed:
initialise the implementation directly in the spy level:
#Spy
lateinit var someFunction: SomeFunctionContract = = object : SomeFuntionContract {
override fun save(test: String) {
testData = test //breakpoint here but never executes
}
override fun get(): String {
return testData
}
}

Mockito: stub function is not working

I am using Mockito to write a simple unit test.
Then, a function under test:
public class MyService {
public void getData() {
executor.execute(new MyRunnable() {
#Override
doTask() {
MyRestClient client = getRestClient();
Response resp = client.getFromServer();
persist(resp.getData());
}
});
}
}
protected MyRestClient getRestClient() {
return new MyRestClient();
}
My test case, I want to test doTask() has run & resp.getData() is persisted:
#Test
public void testGetData() {
MyService spyService = spy(MyService.getInstance());
// mock client
MyRestClient mockedClient = mock(MyRestClient.class);
mockedClient.setData("testData");
// stub getRestClient() function to return mocked client
when(spyService.getRestClient()).thenReturn(mockedClient);
// SUT
spyService.getData();
// run the Runnable task.
Mockito.doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Exception {
Object[] args = invocation.getArguments();
Runnable runnable = (Runnable) args[0];
runnable.doTask();
return null;
}
}).when(executor).execute(Mockito.any(Runnable.class));
...
}
As you see above, I stub the getRestClient() function to return a mocked MyRestClient. However when run the test case, it doesn't stub the getRestClient() but run the real function. Why?
[Edit] following comment and review feedback
A rule of thumb is not to mock the class under test. Also your testing will be much easier if your class under test does not use the new keyword. Instead use Factory classes to create objects. There will be no need to use Mockito.spy() only Mockito.mock().
The fact that the following answer requires significant test setup is telling you that MyService has too much reposibility and needs to be simplified. However for the sake of answering your question directly here is how you can refactor your code to support verifying the call to persist() using Mocks.
MyService accepts in the constructor the objects that you will be mocking in your test setup. Having them passed into the constructor allows your JUnit test case to create the Mocks and keep a reference to them for verification later.
public class MyService {
private MyRunnableFactory runFactory;
private MyRestClientFactory restFactory;
private MyRestDao dao;
// inject constructor arguments
public MyService(MyRunnableFactory runFactory, MyRestClientFactory restFactory, MyRestDao dao) {
this.runFactory = runFactory;
this.restFactory = restFactory;
this.dao = dao;
}
public void getData() {
MyRestClient restClient = restFactory.createInstance();
MyRunnable runner = runFactory.createInstance(restClient, dao);
executor.execute(runner);
}
}
MyRunnable is created so that it can be tested in isolation if required. Again we inject the Mock objects into the constructor. It is tempting to inline Runnables as you have written in your question, however you lose the ability to control the new instance being created within you tests.
public class MyRunnable implements Runnable {
private MyRestClient restClient;
private MyRestDao dao;
public MyRunnable(MyRestClient restClient, MyRestDao dao) {
this.restClient = restClient;
this.dao = dao;
}
public void run() {
Response resp = restClient.getFromServer();
dao.persist(resp.getData());
}
}
MyRestDao is created because this is the class that you want to Verify in your test case. I don't see where persist() is defined in your question so we create a Data Access Object (DAO) to implement it.
public class MyRestDao {
public void persist() {
// save to some repository
}
}
Now let's write the test case that uses the above classes. We want to verify that the persist() method has been called
#RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
#Mock MyRestDao dao;
#Mock MyRestClient restClient;
#Mock MyRunnableFactory runFactory;
#Mock MyRestClientFactory restFactory;
#Test
public void testPersistIsCalled() {
Response expectedResponse = new Response("some data"); // real implementation, not mocked
MyRunnable runner = new MyRunnable(restClient, dao); // real implementation, not mocked
when(restFactory.createInstance()).thenReturn(restClient);
when(runFactory.createInstance(restClient, dao)).thenReturn(runner);
when(restClient.getFromServer()).thenReturn(expectedResponse);
when(restClient.getData()).thenReturn(myRunnable);
// method under test
MyService service = new MyService(runFactory, restFactory);
service.getData();
verify(dao).persist(expectedResponse.getData());
}
}
Note that this test case is brittle because it is tightly coupled to the actual implementation of the MyService class. Ideally you want tests that don't need to know about the internal workings of your class under test.

How to use Moq to Prove that the Method under test Calls another Method

I am working on a unit test of an instance method. The method happens to be an ASP.NET MVC 4 controller action, but I don't think that really matters much. We just found a bug in this method, and I'd like to use TDD to fix the bug and make sure it doesn't come back.
The method under test calls a service which returns an object. It then calls an internal method passing a string property of this object. The bug is that under some circumstances, the service returns null, causing the method under test to throw a NullReferenceException.
The controller uses dependency injection, so I have been able to mock the service client to have it return a null object. The problem is that I want to change the method under test so that when the service returns null, the internal method should be called with a default string value.
The only way I could think to do this is to use a mock for the class under test. I want to be able to assert, or Verify that this internal method has been called with the correct default value. When I try this, I get a MockException stating that the invocation was not performed on the mock. Yet I was able to debug the code and see the internal method being called, with the correct parameters.
What's the right way to prove that the method under test calls another method passing a particular parameter value?
I think there's a code smell here. The first question I'll ask myself in such a situation is, is the "internal" method really internal/ private to the controller under test. Is it the controller's responsibility to do the "internal" task? Should the controller change when the internal method's implementation changes? May be not.
In that case, I would pull out a new targeted class, which has a public method which does the stuff which was until now internal to the controller.
With this refactoring in place, I would use the callback mechanism of MOQ and assert the argument value.
So eventually, you will end up mocking two dependancies:
1. The external service
2. The new targeted class which has the controller's internal implementation
Now your controller is completely isolated and can be unit tested independently. Also, the "internal" implementation becomes unit testable and should have its own set of unit tests too.
So your code and test would look something like this:
public class ControllerUnderTest
{
private IExternalService Service { get; set; }
private NewFocusedClass NewFocusedClass { get; set; }
const string DefaultValue = "DefaultValue";
public ControllerUnderTest(IExternalService service, NewFocusedClass newFocusedClass)
{
Service = service;
NewFocusedClass = newFocusedClass;
}
public void MethodUnderTest()
{
var returnedValue = Service.ExternalMethod();
string valueToBePassed;
if (returnedValue == null)
{
valueToBePassed = DefaultValue;
}
else
{
valueToBePassed = returnedValue.StringProperty;
}
NewFocusedClass.FocusedBehvaior(valueToBePassed);
}
}
public interface IExternalService
{
ReturnClass ExternalMethod();
}
public class NewFocusedClass
{
public virtual void FocusedBehvaior(string param)
{
}
}
public class ReturnClass
{
public string StringProperty { get; set; }
}
[TestClass]
public class ControllerTests
{
[TestMethod]
public void TestMethod()
{
//Given
var mockService = new Mock<IExternalService>();
mockService.Setup(s => s.ExternalMethod()).Returns((ReturnClass)null);
var mockFocusedClass = new Mock<NewFocusedClass>();
var actualParam = string.Empty;
mockFocusedClass.Setup(x => x.FocusedBehvaior(It.IsAny<string>())).Callback<string>(param => actualParam = param);
//when
var controller = new ControllerUnderTest(mockService.Object, mockFocusedClass.Object);
controller.MethodUnderTest();
//then
Assert.AreEqual("DefaultValue", actualParam);
}
}
Edit: Based on the suggestion in the comments to use "verify" instead of callback.
Easier way to verify the parameter value is by using strict MOQ behavior and a verify call on the mock after system under test is executed.
Modified test could look like below:
[TestMethod]
public void TestMethod()
{
//Given
var mockService = new Mock<IExternalService>();
mockService.Setup(s => s.ExternalMethod()).Returns((ReturnClass)null);
var mockFocusedClass = new Mock<NewFocusedClass>(MockBehavior.Strict);
mockFocusedClass.Setup(x => x.FocusedBehvaior(It.Is<string>(s => s == "DefaultValue")));
//When
var controller = new ControllerUnderTest(mockService.Object, mockFocusedClass.Object);
controller.MethodUnderTest();
//Then
mockFocusedClass.Verify();
}
"The only way I could think to do this is to use a mock for the class under test."
I think you should not mock class under test. Mock only external dependencies your class under test has. What you could do is to create a testable-class. It would be a class which derives from your CUT and here you can catch the calls to the another method and verify it's parameter later. HTH
Testable class in the example is named MyTestableController
Another method is named InternalMethod.
Short example:
[TestClass]
public class Tests
{
[TestMethod]
public void MethodUnderTest_WhenServiceReturnsNull_CallsInternalMethodWithDefault()
{
// Arrange
Mock<IService> serviceStub = new Mock<IService>();
serviceStub.Setup(s => s.ServiceCall()).Returns((ReturnedFromService)null);
MyTestableController testedController = new MyTestableController(serviceStub.Object)
{
FakeInternalMethod = true
};
// Act
testedController.MethodUnderTest();
// Assert
Assert.AreEqual(testedController.SomeDefaultValue, testedController.FakeInternalMethodWasCalledWithThisParameter);
}
private class MyTestableController
: MyController
{
public bool FakeInternalMethod { get; set; }
public string FakeInternalMethodWasCalledWithThisParameter { get; set; }
public MyTestableController(IService service)
: base(service)
{ }
internal override void InternalMethod(string someProperty)
{
if (FakeInternalMethod)
FakeInternalMethodWasCalledWithThisParameter = someProperty;
else
base.InternalMethod(someProperty);
}
}
}
The CUT could look something like this:
public class MyController : Controller
{
private readonly IService _service;
public MyController(IService service)
{
_service = service;
}
public virtual string SomeDefaultValue { get { return "SomeDefaultValue"; }}
public EmptyResult MethodUnderTest()
{
// We just found a bug in this method ...
// The method under test calls a service which returns an object.
ReturnedFromService fromService = _service.ServiceCall();
// It then calls an internal method passing a string property of this object
string someStringProperty = fromService == null
? SomeDefaultValue
: fromService.SomeProperty;
InternalMethod(someStringProperty);
return new EmptyResult();
}
internal virtual void InternalMethod(string someProperty)
{
throw new NotImplementedException();
}
}