I have this Spring MVC controller:
@Controller
@RequestMapping(value = "/foo")
public class FooController {
@Inject
private FooService fooService;
@RequestMapping(value = "foo/new")
public final String add(final ModelMap model) {
model.addAttribute(fooService.createFoo());
return "foo/detail";
}
@RequestMapping(value = "foo/{id}")
public final String detail(final ModelMap model, @PathVariable long id) {
model.addAttribute(fooService.findById(id));
return "foo/detail";
}
@RequestMapping(value="foo/update", method=RequestMethod.POST)
public final String save(@Valid @ModelAttribute final Foo foo, final BindingResult result, final SessionStatus status,
final RedirectAttributes ra, final HttpServletRequest request) {
if (result.hasErrors()) {
return "foo/detail";
}
fooService.save(foo);
status.setComplete();
Message.success(ra, "message.ok");
return "redirect:foo/list";
}
@RequestMapping( value= "/foo/delete/{id}", method=RequestMethod.POST)
public String delete(@PathVariable final Long id, final SessionStatus status, final RedirectAttributes ra, final HttpServletRequest request){
if (fooService.findByIdWithOtherFoos(id).getOtherFoos().isEmpty()) {
fooService.delete(id);
status.setComplete();
MessageHelper.success(ra, "message.sucess");
} else {
Message.error(ra, "message.error");
}
return "redirect:foo/list";
}
}
And this Service:
@Service
@Transactional(readOnly = true)
public class FooServiceImpl implements FooService {
@Inject
private fooRepository fooRepo;
@Override
public final Foo createFoo() {
return new Foo();
}
@Override
@Transactional(readOnly = false)
public final void save(final Foo foo) {
if (foo.getId() == null) {
foo.setDate(new Date());
}
fooRepo.save(foo);
}
@Override
@Transactional(readOnly = false)
public final void delete(final Long id) {
fooRepo.delete(id);
}
@Override
public final Foo findById(final Long id) {
return fooRepo.findOne(id);
}
@Override
public Foo findByIdWithOtherFoos(Long id) {
Foo foo = fooRepo.findOne(id);
Hibernate.initialize(foo.getOtherFoos());
return foo;
}
@Override
public final Page<Foo> findAll(final Pageable pageable) {
return fooRepo.findAll(pageable);
}
@Override
public final Page<Foo> find(final String filter, final Pageable pageable) {
// TODO Auto-generated method stub
return null;
}
@Override
public final List<Foo> findAll(final Sort sort) {
return fooRepo.findAll(sort);
}
}
What is the best way of testing with JUnit drivers and services to cover all logical conditions? I always end up with a bunch of test lines to cover all logical conditions.
We recommend using MockitoJUnitRunner? Or create classes which create configuration beans. And charge them with ContextConfiguration 'ContextConfiguration (FooServiceImplTestConfiguration.class classes = {})'
How to implement the Given-When-Then pattern?
When it comes to testing Controllers (especially integration testing) i suggest using Spring's MockMVC or Rest-Assured. And example of using Rest-Assured in action can be seen below:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SomeApplication.class)
@WebIntegrationTest(randomPort = true)
@ActiveProfiles(profiles = "test")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class SomeControllerTest {
@Test
public void getAllSomeObjects() {
expect().statusCode(HttpStatus.SC_OK)
.body("", hasSize(2))
.body("[0]", notNullValue())
.body("[1]", notNullValue())
.body("findAll { it.name.equals('TEST1') }", hasSize(1))
.body("findAll { it.name.equals('TEST2') }", hasSize(1))
.when()
.get("/someAddress");
}
}
For testing Services i suggest using Mockito. Additionally Hamcrest Matchers is a useful library for assertions in tests. Example of using both below:
public class SomeServiceTest {
@InjectMocks
private SomeService someService;
@Mock
private SomeInnerService someInnerService;
@Before
public void setUp() {
initMocks(this);
Mockito.when(someInnerService.useMethod("argument")).thenReturn(new SomeObject());
}
@Test
public void testSomeMethod() {
Set<SomeObject> someObjects= someService.someMethod();
assertThat(someObjects, is(notNullValue()));
assertThat(someObjects, is(hasSize(4)));
}
}
You should test both independently.
First create a unit test for your service. You can use Mockito to mock your service dependency as fooRepository.
@Test
public void testFindById() {
when(fooServices.findById(123)).thenReturn(fooSample);
assertThat(what you want);
}
Then, you should create an other unit test for your controller. The easiest way to do that is to use MockMvc provided in spring-test. And in this case, you can use Mockito to mock fooService.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With