为什么我的测试失败了?

时间:2016-12-23 10:59:37

标签: java unit-testing junit mockito

我正在开发一个应用程序,在她内部我必须为我的UserService类编写测试类。 这是我的服务类:

  private static final Logger LOG = LoggerFactory.getLogger("userLogger");

        @EJB
        UserDAO userDAO;

        @Override
        public List<User> list() {
            LOG.info("Get all users!");
            return Optional.ofNullable(userDAO.findAll())
                    .orElse(Collections.emptyList()).stream().map(u -> u.toUser())
                    .collect(Collectors.toList());
        }

        @Override
        public User findById(long id) {
            UserEntity userEntity = userDAO.find((id));
            if (userEntity == null) {
                throw new UserNotFoundException(id);
            }
            LOG.info("User founded with id {}", id);
            return userEntity.toUser();
        }

        @Override
        public User create(User user) {
            if (user == null) {
                throw new ServiceException("Invalid request!");
            }
            UserEntity exists = userDAO.find(user.getId());
            if (exists != null) {
                throw new UserAlreadyExistsException(user.getId());
            }
            UserEntity userEntity = new UserEntity(user);

            userDAO.create(userEntity);
            LOG.info("Created user with id {}. Username is {}. Name is {}. Surname is {}. Email is {}.",
                    userEntity.getUserId(), userEntity.getUsername(), userEntity.getName(),
                    userEntity.getSurname(), userEntity.getEmail());
            return userEntity.toUser();
        }

        @Override
        public User update(long id, User user) {
            if (user == null) {
                throw new ServiceException("Invalid request!");
            }
            UserEntity userEntity = userDAO.find((id));
            if (userEntity == null) {
                throw new UserNotFoundException(id);
            }
            userEntity.update(user);
            userDAO.update(userEntity);
            return userEntity.toUser();
        }

        @Override
        public void delete(long id) {
            UserEntity userEntity = userDAO.find(id);
            if (userEntity == null) {
                throw new UserNotFoundException(id);
            }
            userDAO.delete(userEntity);
            LOG.info("Deleted user with id {}", userEntity.getUserId());
        }

这是我的测试类:

public class UserServiceImplementationTest {

        private static User useric;
        @Spy
        @InjectMocks
        UserService userService;

        @Mock
        UserDAO userDAO;

        @BeforeMethod
        public void setUp() throws Exception {
            MockitoAnnotations.initMocks(this);
            UserEntity userEntity = mock(UserEntity.class);
            willReturn(mock(User.class)).given(userEntity).toUser();
            willReturn(userEntity).given(userDAO).find(1L);
            useric = new User(7, "DDD", "SDSDS", "SAAsd", "qwqwqw@gmail.com");

        }

        @Test
        public void testWhenUserExist() throws Exception {
            // GIVEN
            long userId = 0;

            // WHEN
            User user = userService.findById(userId);

            // THEN
            assertNotNull(user);
            Assert.assertEquals(userId, user.getId());
            //verify(userService, Mockito.times(1)).findById(userId);



        }

        @Test(expectedExceptions = ServiceException.class, expectedExceptionsMessageRegExp = "user-service: User with id: 35 was not found!")
        public void testWhenUserNotExist() throws Exception {
            // GIVEN
            long userId = 35;

            // WHEN
            userService.findById(userId);

            // THEN
            fail();
        }

        @Test
        public void testCreateUser() throws Exception{
            User user = userService.create(useric);
            assertNotNull(user);
            Assert.assertEquals(useric.getName(), user.getName());
            //User userEntity = new User(1, "aaaewwe", "bbbb", "abba", "asa@gmail.com");
            //User user = userService.create(userEntity);
            // Assert.assertEquals(user, user);
            //assertNotNull(user);
           // Assert.assertEquals(userEntity, user);
           // verify(userService, Mockito.times(1)).create(userEntity);
        }

        @Test
        public void testDeleteUser() throws Exception{
            long userId = 1;
            userService.delete(userId);
            verify(userService, Mockito.times(1)).delete(userId);
        }

    }

当我运行此代码时,我收到此错误:

main] INFO userLogger - Created user with id 7. Username is DDD. Name is SAAsd. Surname is SDSDS. Email is qwqwqw@gmail.com.
[main] INFO userLogger - Deleted user with id 0
PASSED: testCreateUser
PASSED: testDeleteUser
PASSED: testWhenUserNotExist
FAILED: testWhenUserExist
com.comtrade.trips.service.user.exception.UserNotFoundException: user-service: User with id: 0 was not found!
    at com.comtrade.trips.service.user.UserService.findById(UserService.java:45)
    at com.comtrade.trips.service.user.UserServiceImplementationTest.testWhenUserExist(UserServiceImplementationTest.java:56)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:104)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:645)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:851)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1177)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
    at org.testng.TestRunner.privateRun(TestRunner.java:756)
    at org.testng.TestRunner.run(TestRunner.java:610)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:387)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:382)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340)
    at org.testng.SuiteRunner.run(SuiteRunner.java:289)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1293)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1218)
    at org.testng.TestNG.runSuites(TestNG.java:1133)
    at org.testng.TestNG.run(TestNG.java:1104)
    at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:236)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:81)


===============================================
    Default test
    Tests run: 4, Failures: 1, Skips: 0
===============================================


===============================================
Default suite
Total tests run: 4, Failures: 1, Skips: 0
===============================================

[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@23986957: 21 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 13 ms
[TestNG] Time taken by org.testng.reporters.jq.Main@1a04f701: 79 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@12b0404f: 10 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter2@7c469c48: 9 ms
[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@1677d1: 41 ms

我不是傻瓜,我知道那个错误意味着什么,但是有人能告诉我测试方法的语法(和逻辑)是否良好以及如何为testUserExist方法编写方法?

提前致谢

编辑:当我改变我的测试方法时,我的测试类现在是这样的:

private static User useric;
@Spy
@InjectMocks
UserService userService;

@Mock
UserDAO userDAO;

@BeforeMethod
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
    UserEntity userEntity = mock(UserEntity.class);
    willReturn(mock(User.class)).given(userEntity).toUser();
    //willReturn(userEntity).given(userDAO).find(0L);
    //useric = new User(7, "DDD", "SDSDS", "SAAsd", "qwqwqw@gmail.com");

}

@Test
public void testWhenUserExist() throws Exception {
    User goran = new User(5, "goran1992", "goran", "palibrk", "palibrk.goran@gmail.com");
    User user = userService.create(goran);
    // GIVEN

    //long userId = 0;

    // WHEN
   // user = userService.findById(goran.getId());

    // THEN
    assertNotNull(user);
    Assert.assertEquals(user.getId(), goran.getId());
    //verify(userService, Mockito.times(1)).findById(userId);



}

@Test(expectedExceptions = ServiceException.class, expectedExceptionsMessageRegExp = "user-service: User with id: 35 was not found!")
public void testWhenUserNotExist() throws Exception {
    // GIVEN
    long userId = 35;

    // WHEN
    userService.findById(userId);

    // THEN
    fail();
}

@Test
public void testCreateUser() throws Exception{
    User user = userService.create(useric);
    assertNotNull(user);
    Assert.assertEquals(useric.getName(), user.getName());
    //User userEntity = new User(1, "aaaewwe", "bbbb", "abba", "asa@gmail.com");
    //User user = userService.create(userEntity);
    // Assert.assertEquals(user, user);
    //assertNotNull(user);
   // Assert.assertEquals(userEntity, user);
   // verify(userService, Mockito.times(1)).create(userEntity);
}

@Test
public void testDeleteUser() throws Exception{
    //long userId = 1;
    userService.delete(useric.getId());
    verify(userService, Mockito.times(1)).delete(useric.getId());
}

我的控制台给了我这个错误:

[main] INFO userLogger - Created user with id 5. Username is goran1992. Name is palibrk. Surname is goran. Email is palibrk.goran@gmail.com.
PASSED: testWhenUserExist
PASSED: testWhenUserNotExist
FAILED: testCreateUser
com.comtrade.trips.common.ServiceException: Invalid request!
    at com.comtrade.trips.service.user.UserService.create(UserService.java:54)
    at com.comtrade.trips.service.user.UserServiceImplementationTest.testCreateUser(UserServiceImplementationTest.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:104)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:645)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:851)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1177)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
    at org.testng.TestRunner.privateRun(TestRunner.java:756)
    at org.testng.TestRunner.run(TestRunner.java:610)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:387)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:382)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340)
    at org.testng.SuiteRunner.run(SuiteRunner.java:289)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1293)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1218)
    at org.testng.TestNG.runSuites(TestNG.java:1133)
    at org.testng.TestNG.run(TestNG.java:1104)
    at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:236)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:81)

FAILED: testDeleteUser
java.lang.NullPointerException
    at com.comtrade.trips.service.user.UserServiceImplementationTest.testDeleteUser(UserServiceImplementationTest.java:98)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:104)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:645)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:851)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1177)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
    at org.testng.TestRunner.privateRun(TestRunner.java:756)
    at org.testng.TestRunner.run(TestRunner.java:610)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:387)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:382)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340)
    at org.testng.SuiteRunner.run(SuiteRunner.java:289)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1293)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1218)
    at org.testng.TestNG.runSuites(TestNG.java:1133)
    at org.testng.TestNG.run(TestNG.java:1104)
    at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:236)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:81)


===============================================
    Default test
    Tests run: 4, Failures: 2, Skips: 0
===============================================


===============================================
Default suite
Total tests run: 4, Failures: 2, Skips: 0
===============================================

[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@2cbb3d47: 22 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 28 ms
[TestNG] Time taken by org.testng.reporters.jq.Main@29176cc1: 73 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@77167fb7: 11 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter2@18ce0030: 12 ms
[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@25d250c6: 51 ms

3 个答案:

答案 0 :(得分:1)

显然,当id运行时,testWhenUserExist() 1的用户不存在。如果您首先使用此方法创建用户,然后检查它是否存在,那么这应该有效(如果您更改了setUp()方法,则可以避免副作用)。您似乎在id方法中创建了setUp() 7的用户。

答案 1 :(得分:0)

在你设置中配置

willReturn(userEntity).given(userDAO).find(1L);

因此,您从null获取userDAO ID 0

您应该更改设置以使用anyLong()(或相当于它的Easymocks)而不是1L,或者将正确的userDAO配置添加到您的测试方法中:

@Test
public void testWhenUserExist() throws Exception {
    // GIVEN
    long userId = 0; 
    willReturn(userEntity).given(userDAO).find(userId);

    // WHEN
    // ...
}

答案 2 :(得分:0)

你为什么要模拟和监视被测试的课程?
一个干净的单元测试应该尽可能自然地测试实现并且只模拟依赖性。
当然,你可以有一些例外,但在你的情况下,我没有看到任何合理的东西使测试逻辑更少直。

在你的情况下,你想要真正模仿的一件事是UserDAOUserService的依赖。
剩余应该是真实和自然的实现。

此外,您还可以模拟由DAO检索的实体。你的测试逻辑很难理解。

最后,在每个测试方法之前执行的一般setup()做了太多事情:它模拟了一些特定的行为。应根据需要执行记录特定的模拟行为。

要在用户存在时测试findById方法,我建议您在检索UserEntity时仅模拟UserDAO的行为。
然后,您要检查的是实际用户检索到您在模拟录制中提供的匹配项 通过这种方式,您可以检查两件事:

  • 使用期望的id参数调用dao(这是调用的,因为它返回的模拟数据仅在您提供预期的id参数时才返回)
  • 该服务按预期应用DAO检索到的toUser()上的UserEntity方法。

当然,用户应该重写equals()和hashCode(),这个断言有意义:

    Assert.assertEquals(actualUser, userEntityByMock.toUser());      

或者您可以按字段检查字段或使用反射。

这是一个片段:

@Mock
private UserDAO userDAOMock;
private UserEntity userEntityByMock;

private UserService service;

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

    // You should add a constructor with a arg for that but you could use
    // reflection to inject the mock if you don't want to open the api of 
    //  the class
    service = UserService(userDAOMock);
    userEntityByMock = new UserEntity(1, "DDD", "SDSDS", "SAAsd", "qwqwqw@gmail.com");

}

@Test
public void findByIdWhenTheUserExists() throws Exception {
    // GIVEN
    long userId = 1;
    Mockito.when(userDAOMock.find(userId)).thenReturn(userEntityByMock);

    // WHEN
    User actualUser = userService.findById(userId);

    // THEN
    Assert.assertEquals(actualUser, userEntityByMock.toUser());      
}