I am creating a Spring application and below are the related controller, repository,test, and the error msg.
My application has no problem in terms of functionality whatsoever but it's not passing this one unit test.
I mainly have a problem with the Expectations method inside the jmockit test unit. I can't see WHY it is keep saying that I am missing an invocation?? Eventhough I do call them at the very last else block of my controller
skillRepository.findAllById((List<Integer>))
job.setSkills((List<Skill>))
I have been combing through others' similar questions here but could not solve my problem. Thank you in advance.
Controller
@PostMapping("add")
public String processAddJobForm(@ModelAttribute @Valid Job newJob,
Errors errors, Model model, @RequestParam int employerId,
@RequestParam List<Integer> skills) {
if(errors.hasErrors() || skills.size()==1){
if(skills.size()==1){
model.addAttribute("skills_error","You have to choose at least one skill");
}
model.addAttribute("title","Add Job");
model.addAttribute("employers",employerRepository.findAll());
model.addAttribute("skills",skillRepository.findAll());
return "add";
}
Optional<Employer> result = employerRepository.findById(employerId);
if(result.isEmpty()){
model.addAttribute("title","Invalid Employer ID: "+employerId);
return "add";
}else{
Employer employer = result.get();
newJob.setEmployer(employer);
List<Skill> skillObjs = (List<Skill>) skillRepository.findAllById(skills);
newJob.setSkills(skillObjs);
jobRepository.save(newJob);
return "redirect:";
}
}
Repository
@Repository
public interface SkillRepository extends CrudRepository<Skill,Integer> {
}
Test unit
/*
* Verifies that HomeController.processAddJobForm queries skillRepository and sets skills properly
* */
@Test
public void testProcessAddJobFormHandlesSkillsProperly (
@Mocked SkillRepository skillRepository,
@Mocked EmployerRepository employerRepository,
@Mocked JobRepository jobRepository,
@Mocked Job job,
@Mocked Errors errors)
throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException {
Class homeControllerClass = getClassByName("controllers.HomeController");
Method processAddJobFormMethod = homeControllerClass.getMethod("processAddJobForm", Job.class, Errors.class, Model.class, int.class, List.class);
new Expectations() {{
skillRepository.findAllById((List<Integer>) any);
job.setSkills((List<Skill>) any);
}};
Model model = new ExtendedModelMap();
HomeController homeController = new HomeController();
Field skillRepositoryField = homeControllerClass.getDeclaredField("skillRepository");
skillRepositoryField.setAccessible(true);
skillRepositoryField.set(homeController, skillRepository);
Field employerRepositoryField = homeControllerClass.getDeclaredField("employerRepository");
employerRepositoryField.setAccessible(true);
employerRepositoryField.set(homeController, employerRepository);
Field jobRepositoryField = homeControllerClass.getDeclaredField("jobRepository");
jobRepositoryField.setAccessible(true);
jobRepositoryField.set(homeController, jobRepository);
processAddJobFormMethod.invoke(homeController, job, errors, model, 0, new ArrayList<Skill>());
}
The Error
Missing 1 invocation to:
org.springframework.data.repository.CrudRepository#findAllById(any Iterable)
on mock instance: org.launchcode.techjobs.persistent.models.data.$Impl_SkillRepository@7030449d
Missing 1 invocation to:
org.springframework.data.repository.CrudRepository#findAllById(any Iterable)
on mock instance: org.launchcode.techjobs.persistent.models.data.$Impl_SkillRepository@7030449d
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: Missing invocations
at org.launchcode.techjobs.persistent.TestTaskFour$1.<init>(TestTaskFour.java:143)
at org.launchcode.techjobs.persistent.TestTaskFour.testProcessAddJobFormHandlesSkillsProperly(TestTaskFour.java:142)
... 1 more
org.launchcode.techjobs.persistent.TestTaskFour > testProcessAddJobFormHandlesSkillsProperly(SkillRepository, EmployerRepository, JobRepository, Job, Errors) FAILED
mockit.internal.expectations.invocation.MissingInvocation
Caused by: mockit.internal.expectations.invocation.ExpectationError at TestTaskFour.java:143
1 test completed, 1 failed
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///Users/JK/Desktop/LaunchCode/LC_Java/assignment-4-techjobs-persistent-edition-suchunkang0822/build/reports/tests/test/index.html
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 2s
4 actionable tasks: 1 executed, 3 up-to-date
It's difficult to tell as you only show the test, and not the rest of the test class. However, I'm guessing that on the tested class, "employerRepository" and "skillsRepoisitory" are likely auto-wired. Assuming so, then you likely want to make use of "@Tested" and "@Injectable" as opposed to "@Mocked". That is, your class is "@Tested" and the thing it needs at construction is passed as @Injectable.
public class DummyTest {
@Tested public HomeController ctrl;
@Injectable protected SkillRepository skillRepository;
@Injectable protected EmployerRepository employerRepository;
@Injectable protected JobRepository jobRepository;
@Test public void testSomething(..) { .. }
}
Your second issue is that you aren't actually testing with the mocks you create. In your test, you created a "real" HomeController via new, and then, via reflection, invoked processAddJobForm(..) on it. It's much simpler:
@Test
public void testProcessAddJobFormHandlesSkillsProperly (
@Mocked Job job,
@Mocked Errors errors)
{
new Expectations() {{
skillRepository.findAllById((List<Integer>) any);
job.setSkills((List<Skill>) any);
}};
Model model = new ExtendedModelMap();
homeController.processAddJobForm(job, errors, model, 0, new ArrayList<Skill>());
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.