2015-08-16 119 views
7

假设我有一个程序,它看起来像这样:使用JMockit和Spring AOP一起

@Component 
public class MainAction { 
    public void doTheAction() { 
     System.out.println("Now doing the action"); 
    } 
} 

@Aspect 
@Component 
public class BeforeAspect { 
    @Autowired 
    private Logger logger; 

    @Before("execution(* thepackagename.MainAction.*(..))") 
    public void doBefore() { 
     logger.log("The @Before advice has run"); 
    } 
} 

@Component 
public class Logger { 
    public void log(String s) { 
     System.out.println(s); 
    } 
} 

,如果我通过Eclipse中运行它工作正常(主要方法esentially调用mainAction.doTheAction()mainAction被Spring创建) 。

现在我想编写一个测试,确保调用doTheAction时调用log方法的方法正确。我们正在使用JMockit进行测试。 (这是我实际面临的问题的一个非常简单的情况;更复杂的记录器通过AOP方面被调用,并且记录错误的值。在开始修复之前,我正在尝试编写一个测试,以确保所记录的值是正确的)

这是我(简化)测试目前的样子:

@RunWith(JMockit.class) 
@ContextConfiguration(locations = {"classpath:Beans.xml"}) 
public class MainActionTest { 
    @Tested 
    private MainAction mainAction; 

    @Test 
    public void testThatLoggerIsCalled(@Injectable Logger logger) { 
     new Expectations() { { 
      logger.log(anyString); 
     } }; 
     mainAction.doTheAction(); 
    } 
} 

@ContextConfiguration可能是无用的。之前我曾尝试@RunWith(SpringJunit4ClassRunner.class),这就是为什么@ContextConfiguration在那里,但没有处理嘲笑的东西。此外,我使用@Tested@Injectable而不是@Autowired@Mocked,遵循this question中的建议;没有,mainAction保持为空。所以现在测试运行,并且Now doing the action出现在输出中。但是The @Before advice has run没有出现(并且即使我不嘲笑Logger也不会出现),并且期望失败。

如何将JMockit和AOP一起使用?

编辑:根据要求,我添加了一些东西来打印classpath属性。这是(除去一些路径名的不重要的部分):

Eclipse workspaces\springtest8\target\test-classes 
Eclipse workspaces\springtest8\target\classes 
C:\eclipse\plugins\org.junit_4.11.0.v201303080030\junit.jar 
C:\eclipse\plugins\org.hamcrest.core_1.3.0.v201303031735.jar 
.m2\repository\org\jmockit\jmockit\1.18\jmockit-1.18.jar 
.m2\repository\junit\junit\4.11\junit-4.11.jar 
.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar 
.m2\repository\org\springframework\spring-context\4.2.0.RELEASE\spring-context-4.2.0.RELEASE.jar 
.m2\repository\org\springframework\spring-aop\4.2.0.RELEASE\spring-aop-4.2.0.RELEASE.jar 
.m2\repository\aopalliance\aopalliance\1.0\aopalliance-1.0.jar 
.m2\repository\org\springframework\spring-beans\4.2.0.RELEASE\spring-beans-4.2.0.RELEASE.jar 
.m2\repository\org\springframework\spring-core\4.2.0.RELEASE\spring-core-4.2.0.RELEASE.jar 
.m2\repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar 
.m2\repository\org\springframework\spring-expression\4.2.0.RELEASE\spring-expression-4.2.0.RELEASE.jar 
.m2\repository\org\aspectj\aspectjrt\1.8.6\aspectjrt-1.8.6.jar 
.m2\repository\org\aspectj\aspectjweaver\1.8.6\aspectjweaver-1.8.6.jar 
.m2\repository\org\springframework\spring-test\4.2.0.RELEASE\spring-test-4.2.0.RELEASE.jar 
.m2\repository\javax\inject\javax.inject\1\javax.inject-1.jar 
/C:/eclipse/configuration/org.eclipse.osgi/bundles/201/1/.cp/ 
/C:/eclipse/configuration/org.eclipse.osgi/bundles/200/1/.cp/ 

编辑2:我得到的东西从库选项卡中的配置移除JUnit4构建路径工作。

回答

3

下面的测试工作正常,使用Spring 3.0或更高版本(测试使用Spring 3.0.7,4.0.5,4.2.0和):

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "classpath:beans.xml") 
public class MainActionTest 
{ 
    @Inject MainAction mainAction; 

    @Test 
    public void testThatLoggerIsCalled(@Mocked final Logger logger) 
    { 
     mainAction.doTheAction(); 

     new Verifications() {{ logger.log(anyString); }}; 
    } 
} 
+0

我仍然在'Method testThatLoggerIsCalled应该没有参数'。我使用Spring 4.1.0 - 也试过4.2.0。此外,Eclipse将我的JUnit设置为3.8.1 - 是否需要更高版本?你是从'javax.inject'还是别的地方使用@Inject? – ajb

+0

这个关于“没有参数”的错误确实也出现在我身上,但是*只有*如果我使用Spring 2.5,它基于旧的JUnit 4.4测试运行器。 JMockit *和* Spring Test 4.1的最低JUnit版本是JUnit 4.5;它不能与3.8.1一起工作(但这可能是另一回事 - 运行时类路径中的junit.jar最可能是JUnit 4.x)。 –

+0

我正在接受答案,以便赏金不会过期。但我会继续努力让版本正确,并且我会保持更新。 – ajb

2

我从来没有用RunWith注释JUnit测试来使用JMockit。从documentation你需要确保JUnit的jar被加载之前junit的或添加javaagent jvm参数。这样您就可以使用Spring的Junit Runner运行测试,并将JMockit作为模拟框架。

+0

是的,这应该工作。我只能补充说,被测试的类的实例化/注入需要由Spring来完成,否则这个方面将不起作用。为了模拟注入的Logger,测试必须使用'@Capturing'而不是'@ Injectable'。 –

+0

这不适合我。我得到'Method testThatLoggerIsCalled应该没有参数'(来自SpringJUnit4ClassRunner.java),如果我使用'@RunWith(JMockit.class)',我不会得到这个参数。我使用的是Maven依赖关系,并且我在'pom.xml中的'junit'上面移动了'jmockit'(实际上,'jmockit'现在是第一个)并且清理并重建了项目。那我还忘记了什么? – ajb

+0

@Rogério我仍然无法使其工作(请参阅以前的评论)。 – ajb