0

I have the following:

Controller class:

@Controller
@RequestMapping("/")
public class MainController {

    @Inject
    @Named("dbDaoService")
    IDaoService dbDaoService;

    @RequestMapping(method = RequestMethod.GET)
    public String init(ModelMap model) {
        List<Tags> tags = dbDaoService.getAllTags();
        model.addAttribute("tags", tags);
        return "create";
    }
}

Service class:

@Service("dbDaoService")
public class DBDaoService implements IDaoService {

    @PersistenceContext(unitName = "MyEntityManager")
    private EntityManager entityManager;

    @Override
    @Transactional
    public List<Tags> getAllTags() {
         if(tags == null) {
            TypedQuery<Tags> query = entityManager.createNamedQuery("Tags.findAll", Tags.class);
            tags = query.getResultList();
        }

        return tags;
    }
}

Test class:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {WebConfig.class})
@WebAppConfiguration
public class MainControllerTest  {

    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext context;

    @Before
    public void setUp() throws Exception {
        mockMvc = MockMvcBuilders
                .webAppContextSetup(context)
                .build();
    }

    @Test
    public void init() throws Exception {
        Tags tag1 = new Tags("first");
        Tags tag2 = new Tags("second");

        DBDaoService mock = org.mockito.Mockito.mock(DBDaoService.class);
        when(mock.getAllTags()).thenReturn(Arrays.asList(tag1, tag2));

        mockMvc.perform(get("/"))
            .andExpect(status().isOk())
            .andExpect(view().name("create"))
            .andExpect(forwardedUrl("/WEB-INF/views/create.jsp"))
            .andExpect(model().attribute("tags", hasItem(
                    allOf(
                            hasProperty("name", is("first"))
                    )
            )))
            .andExpect(model().attribute("tags", hasItem(
                    allOf(
                            hasProperty("name", is("second"))
                    )
            )));
    }
}

When I run MainControllerTest, it fails, because it gets "Tag" entities from DBDaoService (it means, from database), but I expect it will use mock service.

What's wrong?

3

1 Answer 1

3

The current test setup loads the spring configuration and uses the WebApplicationContext to handle request due to MockMvcBuilders.webAppContextSetup(context).build();. Thus mocked beans are ignored since they are not instructed to participate.

To interweave them the configuration should be updated to MockMvcBuilders.standaloneSetup(controller).build() instead.

The sample test case should look like below (note the additional mock for MainController and configuration update to MockMvcBuilders.standaloneSetup along with instruction to use Mockito annotation via MockitoAnnotations.initMocks)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {WebConfig.class})
@WebAppConfiguration
public class MainControllerTest  {

    private MockMvc mockMvc;

    @InjectMocks
    private MainController controller;

    @Mock
    private DBDaoService daoService;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/view/");
        viewResolver.setSuffix(".jsp");

        mockMvc = MockMvcBuilders.standaloneSetup(controller)
                             .setViewResolvers(viewResolver)
                             .build();

        Tags tag1 = new Tags("first");
        Tags tag2 = new Tags("second");

        when(daoService.getAllTags()).thenReturn(Arrays.asList(tag1, tag2));
    }

    @Test
    public void init() throws Exception {

        mockMvc.perform(get("/"))
            .andExpect(status().isOk())
            .andExpect(view().name("create"))
            .andExpect(forwardedUrl("/WEB-INF/views/create.jsp"))
            .andExpect(model().attribute("tags", hasItem(
                allOf(
                        hasProperty("name", is("first"))
                )
            )))
            .andExpect(model().attribute("tags", hasItem(
                allOf(
                        hasProperty("name", is("second"))
                )
            )));
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Ok, that's great! But I still have two problems.First: andExpect(forwardedUrl("/WEB-INF/views/create.jsp")) causes the error: java.lang.AssertionError: Forwarded URL Expected :/WEB-INF/views/create.jsp Actual :create
Second problem: andExpect(model().attribute("tags", hasItem(allOf( hasProperty("name", is("first")))))) works well, but the second andExpect(model().attribute("tags", hasItem(allOf(hasProperty("name", is("second")))))) throws the error NoSuchMethodError: org.hamcrest.Matcher.describeMismatch(Ljava/lang/Object;Lorg/hamcrest/Description;)V
Regarding first problem - see update. Explicit view resolver is required in case of standalone configuration
Regarding second problem (unsure why one statement works and second fails) - Could you try the steps described here and here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.