JMockit - Unexpected invocation - java

I have a simple implementation using JMockit for unit test. The implementations are as following
Team class
public class Team {
private TeamLeader teamLeader;
public Team(TeamLeader teamleader) {
this.teamLeader = teamleader;
}
public boolean hasDiscussion() {
System.out.println("Discussion is hold by " + teamLeader.getName());
Discussion discussion = new Discussion();
return discussion.start();
}
}
TeamLeader class
public class TeamLeader {
private String name;
public TeamLeader(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Discussion class
public class Discussion {
public boolean start() {
return false;
}
}
Then, I have a unit test to test function hasDiscussion as following
#RunWith(JMockit.class)
public class TeamTest {
private Team team;
#Test
public void hasDiscussion(#Mocked TeamLeader teamLeader, #Mocked Discussion discussion) {
new Expectations() {{
teamLeader.getName(); result = "teamleader";
discussion.start(); result = true;
}};
team = new Team(teamLeader);
boolean actualResult = team.hasDiscussion();
new Verifications() {{
assertThat(actualResult, is(true));
}};
}
}
When executing the test, I got the following error
Unexpected invocation of:
entity.Discussion#Discussion()
on instance: entity.Discussion#7b70deb2
when was expecting an invocation of:
entity.Discussion#start()
on mock instance: entity.Discussion#6f93ad02
mockit.internal.UnexpectedInvocation: Unexpected invocation of:
entity.Discussion#Discussion()
on instance: entity.Discussion#7b70deb2
when was expecting an invocation of:
Any ideas for this sort of problem?

This happened because your hasDiscussion method was creating a new instance of Discussion class, and in this case, you can’t mock it.
To solve this you can receive the Discuss class as a parameter of the method and send the mock, our inject the Discuss class in Team class constructor.

Related

Flink Filter function Testing

I am trying to find the way to test RichFilter function just like RichMappFunction like present here : RichMapFunction Testing is present here......Searched through internet and find nothing...Please help...
public class Person{
public String name;
public Int age;
}
public class OCRKafkaFilter extends RichFilterFunction<Person> {
#Override
public boolean filter(Person person) {
return person.age>21;
}
}
How can we write a test case for this rich filter function for stateful operators ...
You can up a test harness for a filter function doing something like this:
private OCRKafkaFilter function;
private OneInputStreamOperatorTestHarness<Person, Person> harness;
#BeforeEach
void setUpHarness() throws Exception {
function = new OCRKafkaFilter();
StreamFilter<Person> operator = new StreamFilter<>(function);
harness = new OneInputStreamOperatorTestHarness<>(operator);
harness.open();
}
In the example you gave, the RichFilterFunction isn't stateful. In that case you can write tests like this:
public class FilterFunctionTest {
#Test
public void testFilter() {
OCRKafkaFilter filter = new OCRKafkaFilter();
Person person21 = new Person(21);
Person person22 = new Person(22);
assertEquals(false, filter.filter(person21));
assertEquals(true, filter.filter(person22));
}
}

How do I write JUnit test to cover both branches of an if statement

New in JUnit here. I am using JUnit 4 with Mockito. How do I write junit for "if" condition?
Note: I am trying to cover inside the if statement when question is not null. Hopefully my question makes sense.
public class MyClass{
private HttpServletRequest request;
private A a;
private B b;
public void go(String something, String s){
MyQuestion question = Exam.getSubject().getMarks(a.getAId, b.getBId(), something);
if(question !=null){
request.setAttribute(s, question);
}
}
}
// getMarks I do have catching an exception
Here is the snippet:
public class MarksClass{
Public MyQuestion getMarks(long idA, long IdB, String s){
try{
//some code
}catch(Exception e){
throw new SomeException("exception" + e);
}
}
}
Assuming, "getSubject" returns a field with name "subject".
final HttpServletRequest mockedRequest = Mockito.mock(HttpServletRequest.class);
ReflectionTestUtils.setField(myClass, "request", mockedRequest);
final MarksClass mockedMarksClass = Mockito.mock(MarksClass.class);
final MyQuestion mockedResult = Mockito.mock(MyQuestion.class);
Mockito.when(mockedMarksClass.getMarks(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString()).thenReturn(mockedResult);
ReflectionTestUtils.setField(myClass, "subject", mockedMarksClass);
//... rest of the test
Design your class in such a way that testing becomes easy. Or change the design so that it can be tested more easily.
Having global singletons makes testing difficult, if not impossible. The general way forward is to have a class injected with all its external dependencies (DI, dependency injection) or pass the dependencies as arguments to the method.
public class MyClass {
private HttpServletRequest request;
private A a;
private B b;
private final Supplier<Subject> subjectFactory;
public MyClass(final Supplier<Subject> subjectFactory) {
this.subjectFactory = subjectFactory;
}
public void go(String something, String s){
final MyQuestion question = subjectFactory.get().getMarks(a.getAId, b.getBId(), something);
if(question !=null){
request.setAttribute(s, question);
}
}
}
Then in your real code, initialize the class with a method reference to the method on your singleton:
final MyClass myClass = new MyClass(Exam::getSubject);
And in your test inject a test double:
new MyClass(() -> new Subject() {
#Override
public MyQuestion getMarks(…) {
return null;
}
);
Of course, nothing is prevent you from changing the Supplier<Subject> to a Supplier<MyQuestion>, Function<String, MyQuestion>, or a custom interface; and then replacing this with a test double.
#FunctionalInterface
public interface Grader {
MyQuestion getMarks(String idA, String idB, String something);
}
public class MyClass {
private HttpServletRequest request;
private A a;
private B b;
private final Grader grader;
public MyClass(final Grader grader) {
this.grader = grader;
}
public void go(String something, String s){
final MyQuestion question = grader.getMarks(a.getAId, b.getBId(), something);
if(question !=null){
request.setAttribute(s, question);
}
}
}
And then again in your production code vs your test code:
final MyClass production = new MyClass(Exam.getSubject()::getMarks);
final MyClass underTest = new MyClass((a, b, something) -> null);
Providing different implementations of this interface can make your code a bit more expressive:
public class ExamSubjectGrader implements Grader {
#Override
public MyQuestion getMarks(String idA, String idB, String something) {
return Exam.getSubject().getMarks(idA, idB, something);
}
}
public class NullGrader implements Grader {
#Override
public MyQuestion getMarks(String idA, String idB, String something) {
return null;
}
}
MyClass production = new MyClass(new ExamSubjectGrader());
MyClass underTest = new MyClass(new NullGrader());
(both of those are actually singletons, but they could have their own dependencies or state).
And as you can see: you don't even need a heavy mocking library such as Mockito. Good ol' Java can do that just fine.
Find more details in the question Why is my class not using my mock in unit test?

SpringBoot Test ERROR ( Cannot resolve method 'thenReturn(Entity) )

Hello i write and backend service that sells flight tickets and i'm trying to write tests for this api. When i try to write createAirlineCompany test for AirlineCompanyController class i get this error.
Cannot resolve method 'thenReturn(flight.flightticketapp.entities.AirlineCompany)'
My test class:
#Test
public void testCreateAirlineCompany()
{
AirlineCompany airlineCompanyNew = new AirlineCompany();
airlineCompanyNew.setName("RYANAIR");
when(airlineCompanyService.createAirlineCompany(airlineCompanyNew.getName())).thenReturn(airlineCompanyNew);
ResponseEntity<AirlineCompany> airlineCompanyResponseEntity = testRestTemplate.postForEntity
(ROOT_URL+"/airlinecompany/airlineCreate",airlineCompanyNew,AirlineCompany.class);
AirlineCompany airline = (AirlineCompany) airlineCompanyResponseEntity.getBody();
assertNotNull(airlineCompanyResponseEntity.getBody());
assertEquals(airlineCompanyNew.getName(),airline.getName());
}
}
and my AirlineCompanyService class:
#Service
public class AirlineCompanyManager implements AirlineCompanyService {
#Override
public Result createAirlineCompany(String name) {
return airlineCompanyAbstract.createAirlineCompany(name);
}
}
My AirlineCompany Imp class:
#Component
public class AirlineCompanyImp implements AirlineCompanyAbstract {
#Override
public Result createAirlineCompany(String name) {
AirlineCompany airlineCompany = new AirlineCompany();
airlineCompany.setName(name);
add(airlineCompany);
return new SuccessResult(Messages.airlineCompanyCreated);
}
#Override
public Result add(AirlineCompany airlineCompany) {
airlineCompanyRepository.save(airlineCompany);
return new SuccessResult(Messages.airlineCompanyAdded);
}
}
The error i got is coming from thenReturn() method and i don't know how to fix this. Thank you for all.
Make sure you have imported correct static methods when()
import static org.mockito.Mockito.when;
You have a mismatch of the return value you use for the mock.
When specifying the mock you return an AirlineCompany:
when(airlineCompanyService.createAirlineCompany(airlineCompanyNew.getName())).thenReturn(airlineCompanyNew);
But your AirlineCompanyService returns a Result:
public Result createAirlineCompany(String name)
Mockito searches for a method returning an AirlineCompany - which does not exist. You have to return a Result from your mock, e. g.
when(airlineCompanyService.createAirlineCompany(airlineCompanyNew.getName())).thenReturn(new Result());

Mockito problems and says undefinied type while ı am testing my service

I am writing unit test but I am facing an error some how. I am triyng to test my ServiceImpl just showing my entire code down below My code below;
My Service Class
#Service
public class PlaneServiceImpl implements PlaneCallerService {
private final PlaneFactory planeFactory;
public PlaneServiceImpl(PlaneFactory planeFactory) {
this.planeFactory = planeFactory;
}
#Override
public String getPlaneType(String planeType) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(planeFactory.getPlane(planeType).getType());
stringBuilder.append(" Plane has produced.");
return stringBuilder.toString();
}
Plane class down below
public interface Plane {
String getType();
}
My PlaneFactory class down below;
#Component
public class PlaneFactory {
public Plane getPlane(String planeType) {
if (StringUtils.isBlank(planeType)) {
throw new PlaneTypeNotFoundException();
}
if (planeType.equalsIgnoreCase("lightJet")) {
return new LightJet();
} else if (planeType.equalsIgnoreCase("midJet")) {
return new MidJet();
My Mock Test just down below
public class PlaneCallerServiceImplTest {
private PlaneFactory planeFactory;
private PlaneCallerService planeCallerService;
private plane plane;
#Before
public void setUp() {
planeFactory = mock(PlaneFactory.class);
planeCallerService = new PlaneCallerServiceImpl(planeFactory);
plane= mock(Plane.class);
}
#Test
public void testPlaneType() {
String planeType = "";
when(planeFactory.getPlane(planeType)).thenReturn(plane);
String result = planeCallerService.getplaneType(planeType);
assertNotNull(result);
}
}
I'm getting The method getPlane(String) is undefined for the type PlaneFactory
I am quite new for unit test and also mock test any help would be appreciate
Thank you in advanced
Your issue is that from the below statement:
when(planeFactory.getPlane(planeType)).thenReturn(plane);
you are returning a mocked response of type Plane but in that mocked response when you call Plane.getType() that method is not implemented.
You can mock the response of that too, add
when(plane.getType()).thenReturn("SOME_MOCKED_STRING");
This should start to work.
Below is the complete test class:
public class PlaneServiceImplTest {
private PlaneFactory planeFactory;
private PlaneServiceImpl planeCallerService;
#Before
public void setUp() {
planeFactory = mock(PlaneFactory.class);
planeCallerService = new PlaneServiceImpl(planeFactory);
}
#Test
public void testPlaneType() {
Plane plane = mock(Plane.class);
when(planeFactory.getPlane(anyString())).thenReturn(plane);
String result = planeCallerService.getPlaneType("Test");
assertNotNull(result);
}
}

How to check that a method is not being called using JUnit Mockito Verify

I have a class for which I am writing a JUnit test. I am trying to test if a particular method is never called.
public class CountryProcess extends AbstractCountryProcess {
private static final Logger log = LoggerFactory.getLogger(CountryProcessor.class);
private static final Long MAX_FILE = 20l;
#Override
protected boolean processCountry(Region region, City city) {
Long maxFile = region.getRequiredLongValue(SIZE);
if (maxFile < MAX_FILE) {
cntDao.addCountryLandMark(city);
}
else {
log.warn("File size was big");
}
return true;
}
And the test class is:
public class CountryProcessTest {
#Rule
public final JUnitRuleMockery context = new JUnitRuleMockery();
private final CntDao cntDao = context.mock(CntDao.class);
#Before
public void setup() {
Injector injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(cntDao.class).toInstance(cntDao);
}
});
}
#Test
public void shouldIgnoreIfFileSizeBiggerThanPermitted() {
//some code to make it trigger ELSE statement above...
verify(cntDao, never()).addCountryLandMark(anyString());
}
}
But this returns the following error:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type $Proxy4 and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
Any idea how I can fix this in the current context. Please give an example using current code so I get a better idea?
You are mixing two mocking frameworks:
jMock - JUnitRuleMockery
Mockito - verify method
Clearly, they are not compatible with each other.
Your verify call looks ok, I believe it will work as soon as it receives a mock created with Mockito (Use Mockito.mock(CntDao.class))
As an alternative to never you can use Mockito.verifyNoMoreInteractions or Mockito.verifyZeroInteractions, but they are less specific.
In addition to the answer from #Lesiak, here is a reproducible example based on your code with both conditions tested and BDD implementation as well (commented out).
#ExtendWith(MockitoExtension.class)
class CountryProcessTest {
#Mock CountryDAO cntDao;
#Mock
Region region;
#Mock
City city;
#InjectMocks
CountryProcess countryProcess;
#Test
void processCountryLargeSize() {
// given
given(region.getRequiredLongValue()).willReturn(100L);
// when
countryProcess.processCountry(region, city);
// then
verifyNoInteractions(cntDao);
// then(cntDao).shouldHaveNoInteractions(); // BDD implementation
}
#Test
void processCountrySmallSize() {
// given
given(region.getRequiredLongValue()).willReturn(10L);
// when
countryProcess.processCountry(region, city);
// then
verify(cntDao).addCountryLandMark(city);
verifyNoMoreInteractions(cntDao);
// then(cntDao).should().addCountryLandMark(any()); // BDD implementation
// then(cntDao).shouldHaveNoMoreInteractions(); // BDD implementation
}
}
The rest of the classes here are provided for reference.
Region
public class Region {
private int size;
public Long getRequiredLongValue() {
return Integer.toUnsignedLong(size);
}
}
AbstractCountryProcess
public abstract class AbstractCountryProcess {
CountryDAO cntDao;
protected abstract boolean processCountry(Region region, City city);
}

Categories