-2

I have simple Spring boot Rest application what returns Users list from database. Application works as expected but test scenario fail with error. After long googling cannot figure out why? It seems that test class cannot access userRepository and instead of calling userRepository.getAllUsers it calls AppController.getAllUsers.

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
……………………………
Caused by: java.lang.NullPointerException
    at com.loan.demo.controller.AppController.getAllUsers(AppController.java:43)
 …………………………………………..

These are my classes: LoanAppApplication

@SpringBootApplication
public class LoanAppApplication {
public static void main(String[] args) {
    SpringApplication.run(LoanAppApplication.class, args);
}
}

Class User.java

@Entity
@Table(name="USERTABLE")
public class User {
private int id;
@NotNull
private String firstName;
@NotNull
private String lastName;
@NotNull
private String persID;
private int blocked;
private Set<Loan> loans;

public User() {
}
public User(String firstName, String lastName, String persID) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.persID = persID;
}

UserRepository:

@Repository
public interface UserRepository extends JpaRepository<User, Integer>{
    public User findById(int Id);
    public User findByPersID(String userId);
}

And Rest Controller:

@RestController
public class AppController {

    @Autowired
    UserRepository userRepository;

    @GetMapping("/doit")
    public String doIt() {
        return "Do It";
    }

    //list all users
    @GetMapping("/users")
    public List<User> getAllUsers() {
        return userRepository.findAll(); // this is line 43 from debuging error log
    }
}

And test class:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {LoanAppApplication.class})
public class LoanAppApplicationTests {

    private MockMvc mockMvc;

    @InjectMocks
    private AppController appController;

    @Before
    public void addData() {
        mockMvc = MockMvcBuilders.standaloneSetup(appController)
                .build();
    }
    //First test scenario that return only string works perfectly
    @Test
    public void testData() throws Exception {
        mockMvc.perform(get("/doit")
                )
        .andExpect(status().isOk())
        .andExpect(content().string("Do It"));
    }
    //but second that should return empty json string fails with exception
    @Test
    public void testGet() throws Exception {
        mockMvc.perform(get("/users")
                )
        .andExpect(status().isOk())
        .andExpect(content().string("Do It")); //this test should fail but not return exception
    }
}
dkb
  • 4,389
  • 4
  • 36
  • 54
DD3
  • 25
  • 1
  • 3

1 Answers1

1

You need to mock your userRepository

@Mock
UserRepository userRepository;

so after @Mock you need to initialize Mock`s in @Before, add this:

MockitoAnnotations.initMocks(this);

then in code setup what users you want to get

User user = new User();
when(userRepository.getUsers()).thenReturn(Collections.singletonList(user));

and then check

verify(userRepository, times(1)).getUsers();
verifyNoMoreInteractions(userRepository);

this is because you application context is not working