Vlad Starostenko
Vlad Starostenko

Reputation: 141

Redirected URL expected: </> but was<null> in Junit

I have the following classes:

Store.java

@Controller
public class Store {

    @Autowired
    private List<Products> products;

    @GetMapping(value = "cart/busket")
    public String busket() {
        return "redirect:/cart/index";
    }

    @GetMapping(value = "/")
    public String index(final ModelMap model) {

        model.addAttribute("products", this.products);
        return "product/index";
    }

    @GetMapping(value = "cart/buy/{id}")
    public String buy(@PathVariable("id") final String id, final HttpSession session) {

        //some logic

        return "redirect:/";
  }
//and other methods
}

Main.java - which runs the application

@SpringBootApplication
@Configuration
@ImportResource("classpath*:beans.xml")
public class MainApp {
    public static void main(final String[] args) {

        SpringApplication.run(MainApp.class, args);

    }
}

StoreTest.java - my class with tests

@SpringBootTest
@ContextConfiguration(classes = Store.class, locations = {"classpath*:beans.xml"})
@RunWith(SpringRunner.class)
public class StoreTest {

    @InjectMocks
    private Store   myController;
    private List<Products> products;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        // Process mock annotations
        MockitoAnnotations.initMocks(this);

        // Setup Spring test in standalone mode
        this.mockMvc = MockMvcBuilders.standaloneSetup(this.myController).build();

    }

    @Test
    public void testBusket_StatusOK() throws Exception {
        this.mockMvc.perform(MockMvcRequestBuilders.get("/cart/busket"))
                .andExpect(MockMvcResultMatchers.redirectedUrl("/cart/index"));
    }

    @Test
    public void testBuy_StatusOK() throws Exception {
        this.mockMvc.perform(MockMvcRequestBuilders.get("cart/buy/1"))
                .andExpect(MockMvcResultMatchers.redirectedUrl("/"));
    }

    @Test
    public void testIndex_StatusOK() throws Exception {
        this.mockMvc.perform(MockMvcRequestBuilders.get("/"))
                .andExpect(MockMvcResultMatchers.status().isOk());
    }

}

My testBuy_StatusOK() doesn't work. It says: Redirected URL expected: "/" but was "null". I think this is because my dependencies are not implemented. I tried various ways, but it doesn’t work :\


Updated StoreTest.java

@WebMvcTest(Store.class)
@ContextConfiguration(classes = Store.class, locations = {"classpath*:beans.xml"})
@RunWith(SpringRunner.class)
public class StoreTest {

    @MockBean
    private List<Products> products;

    @Autowired
    private MockMvc        mockMvc;

    @Before
    public void setup() {
        // Process mock annotations
        MockitoAnnotations.initMocks(this);

        // Setup Spring test in standalone mode
        this.mockMvc = MockMvcBuilders.standaloneSetup(this).build();

    }

    @Test
    public void testBusket_StatusOK() throws Exception {
        this.mockMvc.perform(MockMvcRequestBuilders.get("/cart/busket"))
                .andExpect(MockMvcResultMatchers.redirectedUrl("/cart/index"));
    }

    @Test
    public void testBuy_StatusOK() throws Exception {

        this.mockMvc.perform(MockMvcRequestBuilders.get("cart/buy/1"))
                .andExpect(MockMvcResultMatchers.redirectedUrl("/"));
    }

    @Test
    public void testGetProducts_StatusOK() throws Exception {
        this.mockMvc.perform(MockMvcRequestBuilders.get("/"))
                .andExpect(MockMvcResultMatchers.status().isOk());
    }

    @Test
    public void testIndex_StatusOK() throws Exception {
        this.mockMvc.perform(MockMvcRequestBuilders.get("/"))
                .andExpect(MockMvcResultMatchers.status().isOk());
    }

}

Updated 2

Beans.xml - the file with beans

<beans>

...


<bean id="product1"
    class="...entities.Products">
    <constructor-arg name="name" value="Cherry" />
    <constructor-arg name="description" value="This is very good cherry" />
    <constructor-arg name="price" value="500" />
    <constructor-arg name="id" value="1" />
  </bean>

  <bean id="product2"
    class="...entities.Products">
    <constructor-arg name="name" value="Cucumber" />
    <constructor-arg name="description" value="This is an amazing cucumber" />
    <constructor-arg name="price" value="1000" />
    <constructor-arg name="id" value="2" />
  </bean>

  <bean id="product3"
    class="...entities.Products">
    <constructor-arg name="name" value="Apple" />
    <constructor-arg name="description" value="This is pretty good apple" />
    <constructor-arg name="price" value="3000" />
    <constructor-arg name="id" value="3" />
  </bean>

  <util:list id="products" value-type="...entities.Products"> <ref bean="product1" /> <ref bean="product2" /> <ref bean="product3" /> </util:list>

</beans>

Upvotes: 0

Views: 1269

Answers (1)

Lesiak
Lesiak

Reputation: 26084

The problem is that MockMvc is completely ignoring myController variable from your test, and uses a controller it created.

To fix:

  • remove private Store myController; from your test
  • to override any dependencies of your Controller, use @MockBean

Also, if you intend to test only the web slice of your app

  • change @SpringBootTest to @WebMvcTest(Store.class)
  • use injected MockMvc @Autowired private MockMvc mockMvc;

Update

If you want to inject a @Bean when using @WebMvcTest you can provide it in your test:

@Configuration
class ProductConfig {
    @Bean
    public List<Product> getProducts() {
        return List.of(new Product());
    }
}

@WebMvcTest(value = Store.class)
@Import({ProductConfig.class})
public class StoreTest {
}

Update2

If you want to read beans from xml file, you can use:

@Configuration
@ImportResource({"classpath:beans.xml"})
class ProductConfig {
}

@WebMvcTest(value = Store.class)
@Import({ProductConfig.class})
public class StoreTest {
}

Upvotes: 2

Related Questions