Jmock unexpected method invocation, cannot see why - java

I have the following method....
public void testa(Car car) {
em.persist(car);
car.setEngine(null);
}
in my test i have:
protected final Car mockCar = context.mock(Car.class);
#Test
public void testCar() {
context.checking(new Expectations() {
{
oneOf(em).persist(car);
oneOf(car).setEngine(null);
}
});
this.stacker.testa(mockCar);
context.assertIsSatisfied();
}
I run this and i keep getting :
unexpected invocation car.setEngine(null)...
If i remove the code that sets the engine in the code and from the test the tests passes... im totally confused as to why this is happening...
exception:
java.lang.AssertionError: unexpected invocation: car.setEngine(null)
no expectations specified: did you...
- forget to start an expectation with a cardinality clause?
- call a mocked method to specify the parameter of an expectation?

Your problem appears to be that you have two Car objects. You have a car, which you set the expectations on, and a mockCar, which you pass through. Without seeing the definitions of these objects, I can't say for sure, but this is probably the root of your problem.
If this isn't the issue, we're going to need more code. Preferably the entire file(s).
For reference, this compiles fine and passes the tests:
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
public class TestyMcTestTest {
private final Mockery context = new Mockery();
private final EntityManager em = context.mock(EntityManager.class);
private final Stacker stacker = new Stacker(em);
private final Car mockCar = context.mock(Car.class);
#Test
public void testCar() {
context.checking(new Expectations() {{
oneOf(em).persist(mockCar);
oneOf(mockCar).setEngine(null);
}});
this.stacker.testa(mockCar);
context.assertIsSatisfied();
}
public interface Car {
void setEngine(Engine engine);
}
public interface Engine { }
public class Stacker {
private final EntityManager em;
public Stacker(EntityManager em) {
this.em = em;
}
public void testa(Car car) {
em.persist(car);
car.setEngine(null);
}
}
private interface EntityManager {
void persist(Object o);
}
}

Related

JMockit verify if private method is called

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.

In Java, How to test void method in Junit Mockito with assertion?

How to test void methods in Mockito with assertSame or assertEquals. I am able to do verify only.
i am getting sonar or PMD rules violation -"JUnit tests should include assert() or fail()".
Below is my sample class with test class.
#Service
public class MyServiceImpl implements IService {
#Autowired
private IDyDBDAO dyDBDAO;
#Override
public void update() {
dyDBDAO.save(getDetailData());
}
#Override
public List<Detail> getCurrentDetail() {
return getDetails(dyDBDAO.findAll());
}
private List<Detail> getDetails(Iterable<Detail> details) {
...blah...
}
private String getPlace(){
Places p = Places.getPlace();//static
return p == null? PlacesUtil.getName("DH"): p.getName;
}
private Detail getDetailData() {
Detail d = new Detail();
d.setName("blah");
d.setDesc("fsdfsdfdsf");
d.setPlace(getPlace());
return d;
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({Places.class, PlacesUtil.class})
public class MyServiceImplTest {
#InjectMocks
private MyServiceImpl myServiceImpl;
#Mock
private IDyDBDAO dyDBDAO;
#Test
public void testGetCurrentDetail() {
given(dyDBDAO.findAll()).willReturn(getMockDetails());
assertSame(myServiceImpl.getCurrentDetail().size(), 2);
}
#Test
public void testUpdate() {
PowerMockito.mockStatic(Places.class);
// first update , second update -us-west-2 will update
given(Places.getPlace()).willReturn(PlacesUtil.getName("UH"))
.willReturn(null);
myServiceImpl.syncStatus();
// update again with DH
myServiceImpl.syncStatus();
verify(dyDBDAO, times(2)).save(any(Detail.class));
// how to assert checking here
}
private Iterable<Detail> getMockDetails() {
Detail d1 = new Detail();
d1.setName("blah");
d1.setDesc("fsdfsdfdsf");
d1.setPlace("sdfsdf");
Detail d2 = new Detail();
d2.setName("blahblah1");
d2.setDesc("e345345");
d2.setPlace("8907j");
List<Detail> listOfDetail = new ArrayList<>();
listOfDetail.add(eps1);
listOfDetail.add(eps2);
return listOfDetail;
}
}
You need to capture the value passed to the dao save method. Use mockito's ArgumentCaptor for that. Then assert on that value.
Something along these lines:
ArgumentCaptor<Detail> captor = ArgumentCaptor.forClass(Detail.class);
verify(dyDBDAO, times(2)).save(captor.capture());
Detail detail1 = captor.getValues().get(0)
assertEquals(expectedDetail, detail1)
I would assume that your void method that needs to be tested is update in MyServiceImpl.
Firstly, you can verify if dyDBDAO.save() is called.
Mockito.verify(dyDBDAO).save(Mockito.anyList...);
Secondly, you can check the modified or created records in the database by retrieving them and comparing to the inputs from getMockDetails.

How do I test Function's code when it's passed as method parameter?

Is it possible to test code that is written in lambda function that is passed inside the method process?
#AllArgsConstructor
public class JsonController {
private final JsonElementProcessingService jsonElementProcessingService;
private final JsonObjectProcessingService jsonObjectProcessingService;
private final JsonArrayProcessingService jsonArrayProcessingService;
public void process(String rawJson) {
jsonElementProcessingService.process(json -> {
JsonElement element = new JsonParser().parse(json);
if (element.isJsonArray()) {
return jsonArrayProcessingService.process(element.getAsJsonArray());
} else {
return jsonObjectProcessingService.process(element.getAsJsonObject());
}
}, rawJson);
}
}
Since the lambda is lazy the function is not invoked (Function::apply) when I call JsonController::process so is there any way to check that jsonArrayProcessingService::process is called?
#RunWith(JMockit.class)
public class JsonControllerTest {
#Injectable
private JsonElementProcessingService jsonElementProcessingService;
#Injectable
private JsonObjectProcessingService jsonObjectProcessingService;
#Injectable
private JsonArrayProcessingService jsonArrayProcessingService;
#Tested
private JsonController jsonController;
#Test
public void test() {
jsonController.process("[{\"key\":1}]");
// how check here that jsonArrayProcessingService was invoked?
}
}
Just make it testable (and readable) by converting it to a method:
public void process(String rawJson) {
jsonElementProcessingService.process(this::parse, rawJson);
}
Object parse(String json) {
JsonElement element = new JsonParser().parse(json);
if (element.isJsonArray()) {
return jsonArrayProcessingService.process(element.getAsJsonArray());
} else {
return jsonObjectProcessingService.process(element.getAsJsonObject());
}
}
The relevant guiding principles I personally follow are:
anytime my lambdas require curly brackets, convert them to a method
organise code so that it can be unit tested
You may need to change the return type of the parse method to match whatever your processing services (which you didn’t show) return.
Given its relatively-basic redirection logic, don't you just want to confirm which of the #Injectables got called:
#Test
public void test() {
jsonController.process("[{\"key\":1}]");
new Verifications() {{
jsonArrayProcessingService.process(withInstanceOf(JsonArray.class));
}};
}

Fields don't match but the test was still passed. [Mockito Test]

I have the following test set up. I don't understand how the test is passing successfully since the user is set to "Dummy."
#RunWith(MockitoJUnitRunner.class)
public class TodoServiceAbstractImplTest
{
#InjectMocks
TodoServiceAbstractImpl todoServiceAbstractImpl = new TodoServiceAbstractImpl();
#Mock
SomeRandomClass someRandomClass;
#Mock
TodoServiceAbstract todoServiceAbstract;
#Test
public void testRetrieveTodo_usingAMock(){
todoServiceAbstractImpl.setUser("Dummy"); //Set the user to be "Dummy" already
assertEquals(null,todoServiceAbstractImpl.getUser()); //Why is the user is still null?
}
}
Here are the relevant classes. I created them to test Mockito as I am still learning testing in Spring Boot.
Definition of the SomeRandomClass:
public class SomeRandomClass{
private String field;
public SomeRandomClass(){
}
public SomeRandomClass(String field){
setRandom(field);
}
public void setRandom(String field){
this.field = field;
}
public String getRandom(){
return field;
}
}
Definition of the Abstract class:
public abstract class TodoServiceAbstract {
#Autowired
private SomeRandomClass RandomUser;
public TodoServiceAbstract(){
//RandomUser = new SomeRandomClass();
}
public void setUser(String user){
this.RandomUser.setRandom(user);
}
public String getUser(){
return RandomUser.getRandom();
}
public abstract List<String> retrieveTodos(String user);
}
Definition of the Abstract Implementation
public class TodoServiceAbstractImpl extends TodoServiceAbstract{
public List<String> retrieveTodos(String user){
if(user == getUser()){
return Arrays.asList("item 1", "item 2",
"item 3");
}
return Arrays.asList("Random item");
}
}
Tom answered in the comments:
Why do you expect something else than null? SomeRandomClass is mocked so it obviously doesn't actually set anything when calling setUser. And why should it? That's the point of a mock.
Remember that mocked implementations are not real, and in particular unstubbed calls will return dummy values such as null, 0, or an empty string.
In addition to what Tom already said in the comments, this test is testing your mocks, rather than your actual implementation. Since you mocked SomeRandomClass, your tests should verify if that method is being called. In this case you should test if SomeRandomClass.setRandom() is called when you call setUser() and likewise, you should test if SomeRandomClass.getRandom() is called when you call getUser().
For example:
#Test
public void getUser_shouldUseGetRandom() {
when(someRandomClass.getRandom()).thenReturn("data");
assertEquals("data", todoServiceAbstractImpl.getUser());
}
To test setUser() you can do something like:
#Test
public void setUser_shouldUseSetRandom() {
todoServiceAbstractImpl.setUser("data");
verify(someRandomClass).setRandom("data");
}
By mocking/stubbing you can write proper unit tests for TodoServiceAbstractImpl without having to take the behaviour of SomeRandomClass.

Test a callback param with Mockito

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.

Categories

Resources