简体   繁体   English

没有使用easymock注入模拟

[英]no injection of a mock with easymock

I want to code a little example using easymock 3.5 and JUnit5, but I get an error (nullPointerException) when trying to inject the mock...我想使用easymock 3.5和JUnit5编写一个小示例,但是在尝试注入模拟时出现错误(nullPointerException)...

here is the test code:这是测试代码:

package model;

import controler.BookEditor;
import org.easymock.EasyMockRule;
import org.easymock.EasyMockSupport;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Before;
import org.junit.Rule;
import org.junit.jupiter.api.Test;
import view.BookWindow;

import static org.junit.jupiter.api.Assertions.assertEquals;

//@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class BookTest extends EasyMockSupport {

@Rule
public EasyMockRule rule = new EasyMockRule(this);


@Mock
public BookWindow bookWindow;

public BookList bookList;

@TestSubject
public BookEditor bookEditor;

@Before
public void setUp() {
  bookList = new BookList();
  bookEditor = new BookEditor(bookList, bookWindow);
}

@Test
public void testBookCreation() {

  Book le_livre_de_la_jungle = new Book("Le livre de la jungle", "Rudyard Kipling",
        "Flammarion",
        "978-2081263246");
  assertEquals(le_livre_de_la_jungle.getTitle(), "Le livre de la jungle");
  assertEquals(le_livre_de_la_jungle.getAuthor(), "Rudyard Kipling");
  assertEquals(le_livre_de_la_jungle.getEditor(), "Flammarion");
  assertEquals(le_livre_de_la_jungle.getISBN(), "978-2081263246");

}


@Test
public void testDisplayBook() {
  bookWindow.setTitle("Le livre de la jungle"); //here is line 53
  bookWindow.setAuthor("Rudyard Kipling");
  bookWindow.setEditor("Flammarion");
  bookWindow.setISBN("978-2081263246");
  replayAll();

  bookEditor.setActiveBook(new Book("Le livre de la jungle",
        "Rudyard Kipling", "Flammarion", "978-2081263246"));
  verifyAll();

}

} }

the first test is ok, but testDisplayBook fails because bookWindow is null.第一个测试没问题,但 testDisplayBook 失败,因为 bookWindow 为空。

in my POM, I have this:在我的 POM 中,我有这个:

<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-launcher</artifactId>
        <version>RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>RELEASE</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
        <version>4.12.1</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-runner</artifactId>
        <version>RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.easymock</groupId>
        <artifactId>easymock</artifactId>
        <version>3.5</version>
        <scope>test</scope>
    </dependency>

</dependencies>

here is the exception:这是例外:

java.lang.NullPointerException at model.BookTest.testDisplayBook(BookTest.java:53) 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.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:389) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:167) at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:163) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:110) at org.jun java.lang.NullPointerException at model.BookTest.testDisplayBook(BookTest.java:53) 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.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:389) at org .junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115) 在 org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:167) 在 org.junit.jupiter. engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40) 在 org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:163) 在 org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute TestMethodTestDescriptor.java:110) 在 org.jun it.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute$3(HierarchicalTestExecutor.java:83) at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:77) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$null$2(HierarchicalTestExecutor.java:92) it.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute$3(HierarchicalTestExecutor.java:83) at org.junit.platform .engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:77) 在 org.junit.platform.engine.support .hierarchical.HierarchicalTestExecutor.lambda$null$2(HierarchicalTestExecutor.java:92)

thank you.谢谢。

In JUnit 5 Rules can't be used any more.在 JUnit 5 中不能再使用Rules了。 You have to use an Extension and annotate the test class or method with ExtendWith .您必须使用Extension并使用ExtendWith注释测试类或方法。 Furthermore you have to use @BeforeEach instead of @Before ( See also the migration section in the user guide ).此外,您必须使用@BeforeEach而不是@Before另请参阅用户指南中的迁移部分)。

Update: Since EasyMock 4.1, EasyMock ships with a JUnit 5 extension out of the box.更新:从 EasyMock 4.1 开始,EasyMock 附带了一个开箱即用的JUnit 5 扩展

As far as I know there is no official EasyMock extension yet.据我所知,目前还没有官方的 EasyMock 扩展。 Luckily the EasyMockRule can be ported quite easily:幸运的是EasyMockRule可以很容易地移植:

import org.easymock.EasyMockSupport;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestInstancePostProcessor;

public class EasyMockExtension implements TestInstancePostProcessor {

    @Override
    public void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception {
        EasyMockSupport.injectMocks(testInstance);
    }
}

Now you can annotate your test class:现在您可以注释您的测试类:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;

// ...

@ExtendWith(EasyMockExtension.class)
public class BookTest extends EasyMockSupport {

    @Mock
    public BookWindow bookWindow;

    public BookList bookList;

    @TestSubject
    public BookEditor bookEditor;

    @BeforeEach
    public void setUp() {
        bookList = new BookList();
        bookEditor = new BookEditor(bookList, bookWindow);
    }

    // ...

Approach with JUnit Jupiter使用 JUnit Jupiter 的方法

I think one of the problem with your code is that it uses a mix of JUnit 4 and JUnit 5 annotations.我认为您的代码的问题之一是它混合使用了 JUnit 4 和 JUnit 5 注释。 Based on your stack trace, I believe you use a JUnit 5 test engine, therefore you should replace the annotation @Before with @BeforeEach .根据您的堆栈跟踪,我相信您使用的是 JUnit 5 测试引擎,因此您应该将注释@Before替换为@BeforeEach

I reproduced your problem with Eclipse Oxygen with JUnit support.我在 JUnit 支持下使用 Eclipse Oxygen 重现了您的问题。 I got past the NullPointerException by replacing annotation-based injections with explicit instantiations:我通过用显式实例替换基于注释的注入来NullPointerException

public class BookTest extends EasyMockSupport {
    public BookWindow bookWindow;
    public BookList bookList;
    public BookEditor bookEditor;

    @BeforeEach
    public void setUp() {
        bookWindow = EasyMock.mock(BookWindow.class);
        bookList = new BookList();
        bookEditor = new BookEditor(bookList, bookWindow);
    }
    ...
}

I don't have the implementation of Book , BookList , BookEditor and BookWindow so I could not verify if the test passed, but at least it runs and bookWindow could be defined.我没有BookBookListBookEditorBookWindow的实现,所以我无法验证测试是否通过,但至少它可以运行并且可以定义bookWindow

Approach with JUnit 4使用 JUnit 4 的方法

This being said, I tried to execute your code with JUnit 4 (replacing JUnit Jupiter @Test annotation with @org.junit.Test . This yielded the following exception:话虽如此,我尝试使用 JUnit 4 执行您的代码(用@org.junit.Test替换 JUnit Jupiter @Test注释。这产生了以下异常:

java.lang.NullPointerException: Have you forgotten to instantiate bookEditor?
at org.easymock.internal.Injector.injectMocks(Injector.java:81)
at org.easymock.EasyMockSupport.injectMocks(EasyMockSupport.java:561)
at org.easymock.internal.EasyMockStatement.evaluate(EasyMockStatement.java:42)
...

EasyMock checks @TestSubject is instantiated before injecting the mocks. EasyMock 在注入@TestSubject之前检查@TestSubject是否已实例化。 I believe you wouldn't want to instantiate the BookEditor before injection of the mock since you would end-up with a null bookWindow anyway:我相信您不希望注入模拟之前实例化BookEditor 因为无论如何您最终都会得到一个null bookWindow

public class BookTest extends EasyMockSupport {
    ...
    @Mock
    public BookWindow bookWindow;

    @TestSubject // BookWindow would be null below as not yet injected.
    public BookEditor bookEditor = new BookEditor(bookList, bookWindow);

One possibility could be to remove the @TestSubject annotation from the bookEditor instance variable, and instantiate the BookEditor in the @Before method (as you currently do):一种可能性是从bookEditor实例变量中删除@TestSubject注释,并在@Before方法中实例化BookEditor (正如您目前所做的那样):

public class BookTest extends EasyMockSupport {
    @Rule
    public EasyMockRule rule = new EasyMockRule(this);

    @Mock
    public BookWindow bookWindow;

    public BookList bookList;

    public BookEditor bookEditor;

    @Before
    public void setUp() {
        bookList = new BookList();
        bookEditor = new BookEditor(bookList, bookWindow);
    }
    ...

But you may need the @TestSubject , in which case this solution is not feasible.但您可能需要@TestSubject ,在这种情况下,此解决方案不可行。

Yet another approach is to avoid the @Mock annotation and instantiate the mock explicitly:另一种方法是避免@Mock注释并显式实例化模拟:

public class BookTest extends EasyMockSupport {
    ...
    public BookWindow bookWindow = EasyMock.mock(BookWindow.class);

    @TestSubject
    public BookEditor bookEditor = new BookEditor(bookList, bookWindow); 
    ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM