I have abstract class like this:
abstract class A(val x: String, y: String..){
fun <R1,R2>bla(request:R1):Response<R2>(..)
}
Also I have class that extends abstract:
class B(val bean1:Bean1, val bean2: Bean2): A(bean1.x, bean2.y){
fun doSomething(
<R1,R2>bla(Object())
)}
My test looks like:
#Mock
private lateinit var bean1:Bean1
#Mock
private lateinit var bean2:Bean2
private lateinit b:B
#BeforeAll
fun init(){
MockitoAnnotations.initMocks(this)
b = spy(B(bean1,bean2))
}
#Test
fun `Test`(){
doReturn(Response()).when(b).bla<Class1,Class2>(Object())
}
How I can test method 'bla' without calling real implementation?
In case above, it calls real implementation every time. I tried to use mock instead spy, but result the same.
Halp!:)
I solved this problem by using interface instead abstract class.
Related
New to Mockito.
I am testing a function inside class A, inside the class A constructor, I have class B. (I need to use a method from class B). Here's the code:
class A #Inject constructor(
private val bAccessor: B
)
fun buildInfo(number, name): Map<String,String> {
val graph = bAccessor.getGraph(
number,
name
)
val filters = GraphParser.getRefinement(graph)
return filters.entries.associate {
val bin = it.key to Bin
.builder()
.withRestrict(it.value)
.build()
bin
}
}
My unit test is testing the class A - buildInfo function,
Below is my unit test code:
#Mock
private lateinit var graph: Graph
#Mock
private lateinit var b: B
#InjectMocks
private lateinit var a: A
#BeforeEach
fun setup() {
MockitoAnnotations.initMocks(this)
}
#Test
fun `test buildInfo`() {
`when`(b.getGraph("123456", "Test")).thenReturn(graph)
var info = a.buildInfo("123456", "Test")
assertTrue(info.isNotEmpty())
assertTrue(info.containsKey("refinement_key"))
assertEquals("refinement_value", info["refinement_key"])
The test fail because:
java.lang.IllegalArgumentException: Parameter specified as non-null is null:
method GraphParser.getRefinement, parameter graph
at GraphParser.getRefinement(GraphView.kt)
at A.buildInfo(A.kt:178)
getRefinement method can only accept the Graph object. I don't want to actually call the b, so I've mocked the answer above like this:
`when`(b.getGraph("123456", "Test")).thenReturn(graph)
But why it indicates the graph is null even if I return a graph?
A parenthesis is missed before thenReturn:
_actual: `when`(b.getGraph("123456", "Test").thenReturn(graph)
correct: `when`(b.getGraph("123456", "Test")).thenReturn(graph)
^
missed symbol
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.
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.
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
}
}
I have a class under test whose constructer looks like this :
public class ClassUnderTest {
ClientOne clientOne;
ClientTwo clientTwo;
OtherDependency otherDependency;
#Inject
public ClassUnderTest(MyCheckedProvider<ClientOne> myCheckedProviderOne,
MyCheckedProvider<ClientTwo> myCheckedProviderTwo,
OtherDependency otherDependency) throws Exception {
this.clientOne = myCheckedProviderOne.get();
this.clientTwo = myCheckedProviderTwo.get();
this.otherDependency = otherDependency;
}
.
.
.
}
And the CheckedProvider looks thus :
public interface MyCheckedProvider<T> extends CheckedProvider<T> {
#Override
T get() throws Exception;
}
I could mock the clients, but how do I initialise the providers with my mocked clients.I use a combination of junit and mockito for writing tests.Any inputs would be appreciated.
What you could do is to mock providers rather than clients. ClientOne and ClientTwo are the types you are passing into your generic class, they are not variables and hence not something you want to mock. In contrast, the providers you are passing to the constructor are really variables, and what you need to control (simulate) are the behaviors of these variables.
public class ClassTest {
private static final CientOne CLIENT_ONE = new ClientOne();
private static final ClientTwo CLIENT_TWO = new ClientTwo();
#Mock
private MyCheckedProvider<ClientOne> providerOne;
#Mock
private MycheckedProvider<ClientTwo> providerTwo;
private ClassUnderTest classUnderTest;
#Before
public void setUp() {
when(providerOne.get()).thenReturn(CLIENT_ONE);
when(providerTwo.get()).thenReturn(CLIENT_TWO);
classUnderTest = new ClassUnderTest(providerOne, providerTwo, otherDependency);
}
}
As the other answer suggests, you could easily mock the providers, too.
But youMyCheckedProvider don't have to.
You already have an interface sitting there, so what would prevent you from creating something like
class MyCheckedProviderImpl<T> implements MyCheckedProvider<T> {
and that think takes a T object in its constructor and returns exactly that?
That is more or less the same what the mocking framework would be doing.