如何在Mockito单元测试中摆脱NullPointerException

时间:2018-12-15 13:54:46

标签: java spring unit-testing spring-boot mockito

我想对可以租用的req.session方法进行单元测试。

这里是const http = require('http'); const express = require('express'); const socketIO = require('socket.io'); const bodyParser = require('body-parser'); const multer = require('multer'); const consolidate = require('consolidate'); const session = require('express-session'); const app = express(); const server = http.Server(app); const io = socketIO(server); app.use(session({ secret: 'zazagelovidzudzua', resave: false, saveUninitialized: true })) app.engine('html', consolidate.mustache); app.set('view engine', 'html'); app.set('views', __dirname + '/views'); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(multer().array()); app.use(express.static('public')); const mongoose = require('mongoose'); const connectionUri = 'mongodb://localhost/my_database'; mongoose.Promise = global.Promise; mongoose .connect(connectionUri, { useNewUrlParser: true }) .then(() => { console.log('Connection to database established'); }) .catch(error => { console.error('MongoDB connection error:', error.message); process.exit(-1); }); const Schema = mongoose.Schema; const UserSchema = new Schema({ username: String, password: String, email: String, friends: [{ type: Schema.Types.ObjectId, ref: 'Friends' }] }); const Friend = new Schema({ name: { type: Schema.Types.ObjectId, ref: 'User' }, age: Number, address: String }) const User = mongoose.model('User', UserSchema); const Friends = mongoose.model('Friends', Friend) // var ses; // don't create this var app.get('/', (req, res) => { res.render('mainpage'); }); app.get('/reg', (req, res) => { res.render('reg'); }); app.post( '/reeg', async (req, res) => { try { const username = req.body.username const password = req.body.password const email = req.body.email const user = await User.create({ username, password, email }); console.log('Created user:', user); res.sendFile(__dirname + '/views/mainpage.html') } catch (error) { res.status(500).send(error.message); } }); app.post('/login', async (req, res) => { ses = req.session try { const { username, password } = req.body; const user = await User.findOne({ username, password }).select('-password').lean(); if (!user) { res.send('User: ' + username + ' not registered'); return; } // ses.user = user req.session.user = user; // assign direct data to session for req return res.status(200).send('Session ID: ' + req.sessionID); // ses.user = user // unreachable statement } catch (error) { res.status(500).send(error.message); } }); app.get('/dash', async (req, res) => { // if (!ses.user) { if (!req.session.user) { res.status(401).send('login first please!') } res.status(200) // res.send('hi' + ses.user.username) res.send({ sessionID: req.sessionID, message: 'Hi ' + req.session.user.username }) }) server.listen('8080');

rentBook

我试图对其进行单元测试,但获得了NPE。我不知道我在做什么错。

@Service

Stacktrace:

package bookrental.service.book.rentals;

import bookrental.model.account.User;
import bookrental.model.book.Book;
import bookrental.model.book.BookRentals;
import bookrental.repository.account.UserRepository;
import bookrental.repository.book.BookRepository;
import bookrental.repository.book.BookRentalsRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class BookRentalService {

    private final UserRepository userRepository;
    private final BookRepository bookRepository;
    private final BookRentalsRepository bookRentalsRepository;

    @Autowired
    public BookRentalService(BookRepository bookRepository, BookRentalsRepository bookRentalsRepository, UserRepository userRepository) {
        this.bookRepository = bookRepository;
        this.bookRentalsRepository = bookRentalsRepository;
        this.userRepository = userRepository;
    }

    public String rentBook(int userID, int bookID) {
        if (userRepository.doesAccountExistsWithGivenID(userID)) {
            if (bookRepository.doesBookExistsWithGivenID(bookID)) {
                Book bookToRent = bookRepository.findOne(bookID);
                if (bookToRent.isAvailable()) {
                    updateBookAvailabilityAndSaveToDb(bookToRent);
                    BookRentals preparedBookToRent = prepareBookToRent(userID, bookID);
                    bookRentalsRepository.save(preparedBookToRent);
                } else {
                    throw new IllegalArgumentException("Book is not available");
                }
            } else {
                throw new IllegalArgumentException("Book does not exist!");
            }
        } else {
            throw new IllegalArgumentException("Account does not exist!");
        }
        return "Book was rented";
    }

    private BookRentals prepareBookToRent(int userID, int bookID) {
        return new BookRentals(new Book(bookID), new User(userID));
    }

    private void updateBookAvailabilityAndSaveToDb(Book bookToRent) {
        bookToRent.setAvailable(false);
        bookRepository.save(bookToRent);
    }

    public List<BookRentals> findAllRentals() {
        List<BookRentals> rentedBooks = new ArrayList<>();
        bookRentalsRepository.findAll().forEach(rentedBooks::add);
        return rentedBooks;
    }
}

/// 编辑

package bookrental.service.book.rentals;

import bookrental.model.account.User;
import bookrental.model.book.Book;
import bookrental.model.book.BookRentals;
import bookrental.repository.book.BookRentalsRepository;
import bookrental.repository.book.BookRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.junit.Assert.*;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class BookRentalServiceTest {

    @Mock
    BookRentalsRepository bookRentalsRepository;
    @Mock
    BookRepository bookRepository;

    @InjectMocks
    BookRentalService bookRentalService;

    @Test
    public void rentBook() {
        Book book = createDummyBook();
        User user = createDummyUser();
        BookRentals bookToRent = createDummyRentedBook(user, book);

       when(bookRentalsRepository.save(bookToRent)).thenReturn(bookToRent);

        bookRentalService.rentBook(user.getId(), book.getId());

        verify(bookRentalsRepository).save(bookToRent);
        verify(bookRentalService, times(1)).rentBook(user.getId(), book.getId());
    }

    @Test
    public void findAllRentals() {
    }

    private Book createDummyBook() {
        return new Book(0, "W pustyni i w puszczy", "Henryk Sienkiewicz", "dramat", true);
    }

    private BookRentals createDummyRentedBook(User user, Book book) {
        return new BookRentals(book, user);
    }

    private User createDummyUser() {
        return new User(0, "must", "123");
    }
}

堆栈跟踪

java.lang.NullPointerException
    at bookrental.service.book.rentals.BookRentalService.rentBook(BookRentalService.java:30)
    at bookrental.service.book.rentals.BookRentalServiceTest.rentBook(BookRentalServiceTest.java:38)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
    at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

1 个答案:

答案 0 :(得分:3)

从堆栈跟踪来看,它似乎失败了,因为您还没有模拟用户存储库。 添加以下内容:

@Mock
UserRepository userRepository;

...

when(userRepository.doesAccountExistsWithGivenID(user.getId()).thenReturn(true);