【问题标题】:Junit cannot Mock a classJunit 不能模拟一个类
【发布时间】:2018-02-15 21:30:16
【问题描述】:

当我尝试使用 PowerMock 和 Mockito 测试方法并模拟其依赖关系时遇到问题。我尝试将依赖方法转换为非静态方法并使用@Mock 注释和@InjectMocks 但根本没有结果。

这里是被测试的类和方法:

/* class to be tested */
public class LoginServiceImpl implements LoginService{

   /* method to be tested */
   @Override
   public String createJwt(String subject, String name, String permission, Date datenow)  throws java.io.UnsupportedEncodingException{
       Date expDate = datenow;
       expDate.setTime(datenow.getTime()+(300*1000));  //expiration time = 30 minutes

       String token = jwtUtils.generateJwt(subject, expDate, name, permission);
       return token;
   }
}

这里有我想模拟的依赖项,但我在模拟时遇到了麻烦:

/* Dependency I cannot mock */
public class JwtUtils {

    public static String generateJwt(String subject, Date date, String name, String scope) throws java.io.UnsupportedEncodingException{
        String jwt = Jwts.builder()
            .setSubject(subject)
            .setExpiration(date)
            .claim("name", name)
            .claim("scope", scope)
            .signWith(
                    SignatureAlgorithm.HS256,
                    "myPersonalSecretKey12345".getBytes("UTF-8")
            )
            .compact();

       return jwt;
   }
}

最后,但并非最不重要的是,带有失败的测试方法的测试类。 我不得不说它甚至没有到达 assert 方法调用,而是在 when().thenResult() 处失败。 我还必须指定我尝试使用 doReturn() 和 any() 作为匹配器,但没有结果。

@RunWith(MockitoJUnitRunner.class)          //to run Mockito
@PrepareForTest({JwtUtils.class})           //powerMock annotations tomock classes containing static methods
public class LoginServiceImplTest {

   @InjectMocks
   LoginServiceImpl loginService;          //System under test (SUT)

   @Test
   public void createJwtTest() throws Exception {

       SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd");
       Date expdate = ft.parse("2040-12-12");
       String jwt = JwtUtils.generateJwt("BDAGPP32E08F205K", expdate, "Pippo Baudo", "conduttore");
       //HERE IT'S WHERE IT FAILS:
       when(JwtUtils.generateJwt("BDAGPP32E08F205K", expdate, "Pippo Baudo", "conduttore")).thenReturn(jwt);

       assertThat(loginService.createJwt("BDAGPP32E08F205K", "Pippo Baudo", "conduttore", expdate), is(jwt));
   }
}

这是 JUnit 和 Mockito 给我的错误:

org.mockito.exceptions.misusing.MissingMethodInvocationException: when() 需要一个必须是“模拟方法调用”的参数。 例如: when(mock.getArticles()).thenReturn(articles);

此外,出现此错误的原因可能是: 1.你存根:final/private/equals()/hashCode()方法。这些方法不能被存根/验证。模拟方法 不支持在非公共父类上声明。 2. 在 when() 中,你不会在 mock 上调用方法,而是在其他对象上调用。

在 com.example.bytecode.SpringBootJWT.services.LoginServiceImplTest.createJwtTest1(LoginServiceImplTest.java:114) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 在 org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 在 org.junit.runners.ParentRunner.run(ParentRunner.java:363) 在 org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) 在 org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) 在 org.junit.runner.JUnitCore.run(JUnitCore.java:137) 在 com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) 在 com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) 在 com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) 在 com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

进程以退出代码 255 结束

【问题讨论】:

  • 试试when(JwtUtils::generateJwt)
  • 您的createJwt() 方法也修改了参数datenow...!
  • 谢谢,但对我没有用

标签: java unit-testing junit mocking stub


【解决方案1】:

尝试将@RunWith(MockitoJUnitRunner.class) 替换为@RunWith(PowerMockRunner.class)。据我所知,所有使用 PowerMock 功能的测试都必须使用 PowerMockRunner 运行。

【讨论】:

    【解决方案2】:

    没有规定实用程序类中的方法必须是static!

    事实上,这是一种不好的做法,因为它会使您的代码高度耦合且不灵活。您替换此依赖项的问题就是证明。

    因此,您应该通过从方法中删除 static 关键字并传入将该类添加到您的单元中,最好使用 DI 框架。 在这种情况下,您可以使用普通的 Mockito 来模拟该依赖项并且替换它没有问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-09
      • 1970-01-01
      • 2014-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-18
      相关资源
      最近更新 更多