I am making a unit test for class in my app, it just a simple class and I thought i did everything right but the test failed saying
Wanted but not invoked:
mContextWeakReference.get();
-> at rahmat.com.app.utility.backwardcompatibility.StringResourceUtilTest.getString(StringResourceUtilTest.java:40)
Actually, there were zero interactions with this mock.
this is the class to be tested
public class StringResourceUtil {
private static StringResourceUtil sInstance;
private WeakReference<Context> mContextWeakReference;
public static StringResourceUtil getInstance() {
return sInstance;
}
#Inject
public StringResourceUtil(Context context) {
mContextWeakReference = new WeakReference<>(context);
sInstance = this; //NOSONAR
}
public String getString(int resId) {
return mContextWeakReference.get().getString(resId);
}}
this is unit test I made
public class StringResourceUtilTest {
private StringResourceUtil mResourceUtil;
#Mock
private Context mContext;
#Mock
private WeakReference<Context> mContextWeakReference;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mResourceUtil = new StringResourceUtil(mContext);
}
#Test
public void getString() {
int resId = 123;
mResourceUtil.getString(resId);
verify(mContextWeakReference).get().getString(eq(resId));
}}
any help would be much appreciated, thanks
Your StringUtil class is always creating a new object of mContextWeakReference object and even if you are making it, it won't inject automatically ( for that you use injectMock but no use here, since new object creation always happens internally).
public class StringResourceUtilTest {
private StringResourceUtil mResourceUtil;
#Mock
private Context mContext;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mResourceUtil = new StringResourceUtil(mContext);
// setup mock return type
// mock objects are not real,so need to moeck the behavior of method as well
when(mContext.getString(R.string.a123)).thenReturn("123");
}
#Test
public void getString() {
int resId = R.string.a123;
// check the return type
assertEquals("123",mResourceUtil.getString(resId));
}
}
Note: To verify the internal working, read
What is the difference between mocking and spying when using Mockito?
Because you creating mContextWeakReference = new WeakReference<>(context); in constructor, it will never been a mock in StringResourceUtil.
You can set prepared mock mContextWeakReference by using
org.springframework.test.util.ReflectionTestUtils.setField(mResourceUtil , "mContextWeakReference", mContextWeakReference);
Otherwise you should modifying StringResourceUtil class to be a testable
Related
I am testig a public method and I want to verify if a private method, that have mocked params, is called.
All the answers I have found are using invoke method, but this was removed since JMockit v1.36
public class ClassToTest{
public void methodToTest(){
DependencyClass abc = new DependencyClass();
if(privateMethod1()){
privateMethod2(abc);
}
}
private boolean privateMethod1(){ return true; }
private void privateMethod2(DependencyClass abc){ abc.doStuff(); }
}
public class testClassToTest{
#Mocked
DependencyClass abc;
#Tested
ClassToTest testedClass;
#BeforeEach
public void setUp() {
testedClass = new ClassToTest();
}
#Test
public void testMethod(){
new MockUp<ClassToTest>() {
#Mock
private boolean privateMethod1() {
return true;
}
};
testedClass.methodToTest();
new FullVerificationsInOrder() {{
abc = new DependencyClass();
//Check here if privateMethod2(abc) gets called once
}};
}
You can use Powermock to mock and verify private methods.
Please check https://github.com/powermock/powermock/wiki/MockPrivate
You have two ways:
To level up your method's scope from private to package-private and after it, your method will become visible in the test.
Refactoring your code and encapsulate the private method to Predicate and after it, you can test your primary method and Predicate separately.
You can't test the private method by Junit.
I'm not very well-versed with Mockito but am trying to use mocks to test behaviour of a simulation, this is the class:
package simulator;
import java.util.Map;
import org.apache.commons.lang3.Validate;
import simulator.enums.Team;
import simulator.fixtures.Fixture;
public class SimulateBasketballMatchResult implements Simulation<Team> {
private final Fixture fixture;
public SimulateBasketballMatchResult(Fixture fixture) {
Validate.notNull(fixture, "fixture cannot be null");
this.fixture = fixture;
}
#Override
public Team simulate(Map<Team, Double> outcomeProbabilityMap) {
Validate.notNull(outcomeProbabilityMap, "outcomeProbabilityMap cannot be null");
final Team homeTeam = fixture.getHomeTeam();
final Team awayTeam = fixture.getAwayTeam();
double random = randomDoubleGenerator();
double homeWinProbability = outcomeProbabilityMap.get(homeTeam);
return random < homeWinProbability ? homeTeam : awayTeam;
}
public Double randomDoubleGenerator() {
return Math.random();
}
}
Below is the test class:
#RunWith(MockitoJUnitRunner.class)
public class SimulateBasketballMatchResultTest {
#Rule
public ExpectedException expectedException = ExpectedException.none();
private static final Map<Team, Double> MATCH_RESULT_PROBABILITY_MAP = new HashMap<>();
private static final Fixture FIXTURE = new Fixture(GOLDEN_STATE_WARRIORS, HOUSTON_ROCKETS, REGULAR_SEASON);
static {
MATCH_RESULT_PROBABILITY_MAP.put(FIXTURE.getHomeTeam(), 0.7d);
MATCH_RESULT_PROBABILITY_MAP.put(FIXTURE.getAwayTeam(), 0.3d);
}
#Mock
private SimulateBasketballMatchResult simulateBasketballMatchResult;
#Test
public void shouldReturnGoldenStateWarriorsAsWinner() {
when(simulateBasketballMatchResult.randomDoubleGenerator()).thenReturn(0.5d);
assertThat(simulateBasketballMatchResult.simulate(MATCH_RESULT_PROBABILITY_MAP), is(GOLDEN_STATE_WARRIORS));
}
}
I would like to assert that GOLDEN_STATE_WARRIORS is returned when the probability range is between 0 and 0.7- however I get an assertion error of null with my test code.
java.lang.AssertionError:
Expected: is <GOLDEN_STATE_WARRIORS>
but: was null
Expected :is <GOLDEN_STATE_WARRIORS>
simulateBasketballMatchResult is a mock object, so by default, it will return null for all its methods (that have a non-primitive return value, of course).
Instead of mocking that object, you should probably spy it:
#Spy
private SimulateBasketballMatchResult simulateBasketballMatchResult =
new SimulateBasketballMatchResult(Fixture);
Try this:
#Mock
private Fixture fixture;
private SimulateBasketballMatchResult simulator;
#Before
public void setUp() {
simulator = spy(new SimulateBasketballMatchResult(fixture));
doCallRealMethod().when(simulator).simulate();
}
#Test
public void shouldReturnGoldenStateWarriorsAsWinner() {
doReturn(0.5).when(simulator).randomDoubleGenerator();
when(fixture.getHomeTeam()).thenReturn(GOLDEN_STATE_WARRIORS);
when(fixture.getAwayTeam()).thenReturn(HOUSTON_ROCKETS);
assertThat(simulator.simulate(MATCH_RESULT_PROBABILITY_MAP), is(GOLDEN_STATE_WARRIORS));
}
Mockito.spy and #Spy allow you to mock some methods of a real object, but Mockito.mock and #Mock mock the whole object.
A mock in mockito is a normal mock (allows you to stub invocations; that is, return specific values out of method calls).
A spy in mockito is a partial mock (part of the object will be mocked and part will use real method invocations).
Read more
I got pretty simple Dictionary class that makes a call to external API.
public class Dictionary {
protected ExternalService service = new ExternalService();
public String getValue(String key, String dictionaryName) {
ExternalServiceInput input = new ExternalServiceInput();
ExternalServiceOutput output = new ExternalServiceOutput();
input.setKey(key);
input.setDictionaryName(dictionaryName);
try {
output = service.invoke(input);
} catch (Exception e) {
return null;
}
return output.getValue();
}
}
It works fine, but I wanted to write Unit Tests for this, so I decided I need to mock service.invoke().
#Mock
private ExternalService service;
#InjectMocks
private Dictionary dictionary;
#InjectMocks
private ExternalServiceOutput output;
#InjectMocks
private ExternalServiceInput input;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
input.setKey("testKey");
input.setDictionaryName("testDictionary");
output.setValue("testValue");
}
#Test
public void shouldReturnValue() throws Exception {
when(service.invoke(input)).thenReturn(output);
assertEquals(output.getValue(), dictionary.getValue(input.getKey(), input.getDictionaryName()));
}
I'v tried with Input and Output as regular field or initialize it in setUp method, everything ends up with NullPointerException at Dictionary class at
return output.getValue();
Can someone point me what I did wrong?
You should override equals and hashCode in your ExternalServiceInput class or change your mock to accept any object of ExternalServiceInput
when(service.invoke(Mockito.any(ExternalServiceInput.class))).thenReturn(output);
I'm pretty new in unit testing and dont know how to test the following circunstances over a callback for this example class:
public class Foo {
private final ItemLoader loader;
private Bar bar;
public Foo(ItemLoader loader,Bar bar) {
super();
this.loader = loader;
this.bar=bar;
}
public void getItems(ItemStore.Callback callback) {
List<ItemData> itemData = bar.getItemData();
List<Item> items = this.loader.transform(itemData);
callback.onItemsLoaded(items);
}
}
That callback.onItemsLoaded is called with the result of loader.transform
My current test is:
public class ExampleTest extends BaseTestCase {
private Foo foo;
#Mock
private Bar mockBar;
#Mock
private ItemLoader mockItemLoader;
#Mock
private ItemStore.Callback itemLoadCallback;
public void setUp() {
MockitoAnnotations.initMocks(this);
foo = new Foo(mockItemLoader, mockBar);
}
public void testGetItems() {
List<ItemData> mockItemData = (List<ItemData>) mock(List.class);
when(mockBar.getItemData()).thenReturn(mockItemData);
foo.getItems(itemLoadCallback);
verify(mockItemLoader).transform(mockItemData);
}
}
It tests:
That loader.transform is called
That callback.onItemsLoaded is called
But I realised that if I change the last line of the Foo.getItems method like (Notice the null):
public void getItems(ItemStore.Callback callback) {
...
callback.onItemsLoaded(null);
}
The test keep pasing. So I'd need to test that callback.onItemsLoaded is called with the result of loader.transform
So I modified the test:
public void testGetItems() {
List<ItemData> mockItemData = (List<ItemData>) mock(List.class);
when(mockBar.getItemData()).thenReturn(mockItemData);
foo.getItems(itemLoadCallback);
verify(mockItemLoader).transform(mockItemData);
List<Item> resultItems = verify(mockItemLoader).transform(mockItemData);
verify(itemLoadCallback).onItemsLoaded(resultItems);
}
But it complains in the last line saying Argument(s) are different!
How can I fix the test
Because mockItemLoader is a mock, it will actually return an empty list from transform. If you want to make it return something different, you could set up an object for it to return. Basically, this will be your own List<Item>. So you can then stub the tranform method instead of verifying it; and use the same List<Item> when you verify the call to onItemsLoaded.
I used to rely on Mockito until today I have a final class with some static methods so I've to switched to JMockit. I knew nothing about it before so the question is: how can I apply the similar logic from Mockito to JMockit?
public final class ServiceData extends BaseData {
private List<Data> data;
public ServiceData(List<Data> data) {
this.data = data;
// something else
}
public static Container getContainer() {
return super.getContainer();
}
public Data getDataAt(Index index) {
return super.getContainer().get(index);
}
}
The test written in Mockito looks like:
#Test
public void test() {
ServiceData mockServiceData = mock(ServiceData.class);
Data mockData = mock(Data.class);
// only stubbing some of the methods
Container mockContainer = spy(Container.class);
doReturn(something).when(mockContainer.someMethod());
when(mockServiceData.getContainer()).thenReturn(mockContainer);
when(mockServiceData.getDataAt(any(Index.class)).thenReturn(mockData);
// some assertions
}
This won't work since Mockito cannot mock final classes nor static methods (getContainer)
So how can I write the same logic in JMockit? Thanks.
The following is the JMockit equivalent for the example test:
#Test
public void test(
#Mocked final ServiceData mockServiceData, #Mocked final Data mockData,
#Mocked final Container mockContainer)
{
// only stubbing some of the methods
new Expectations(mockContainer) {{
mockContainer.someMethod(); result = "something";
mockServiceData.getContainer(); result = mockContainer;
mockServiceData.getDataAt((Index) any); result = mockData;
}};
// some assertions
}
To mock static methods the syntax is the same, except that you would write ServiceData.getContainer(); result = mockContainer; instead.