1

Spring FW4 ベースの Java アプリケーションでいくつかのコントローラー メソッドの単体テストを開始したときに、複雑な問題が発生しました。

私の ApplicationConfig.java は @Configuration および @EnableTransactionManagement(proxyTargetClass = true) で注釈が付けられ、単純なエンティティークラスの新しいオブジェクトを保存するために作成した public Controller メソッドは、次の ControllerTestClass でテストされます

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:/test-context.xml"})
@TransactionConfiguration(defaultRollback = true, transactionManager = "annotationDrivenTransactionManager")
public class TestController 
    @Autowired
    public MyClassService myClassServiceMock;

    protected MockMvc mockMvc;

    @Autowired
    protected WebApplicationContext webApplicationContext;

    @Before
    public void setUp() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    };

    @org.junit.Before
    public void reset() {
        Mockito.reset(myClassServiceMock);
    }

    @org.junit.After
    public void after() { 
         verifyNoMoreInteractions(myClassServiceMock);
    }


    @Test
    public void testSaveObject() throws Exception {
        MyObject object = new MyObjectBuilder().withName("object").withDate("2014-08-15").build();
        when(myClassServiceMock.createObject(objectName, objectDate)).thenReturn(object);

        [.. mockMvcTest which works ... ]

        verify(myclassServiceMock, times(1)).createObject(objectName, objectDate);
    }
}

debug.log の次の部分は、問題の原因がわからないものですが、 @EnableTransactionManager-Annotation を削除すると、エラーは発生しません...

2014-08-15_17:25:59.608 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Creating new transaction with name [a.b.c.MyClassService$$EnhancerByMockitoWithCGLIB$$cf62a86c.saveObject]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2014-08-15_17:25:59.608 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Opened new EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@513f39c] for JPA transaction
2014-08-15_17:25:59.616 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@320cac01]
2014-08-15_17:25:59.618 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Initiating transaction commit
2014-08-15_17:25:59.618 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Committing JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@513f39c]
2014-08-15_17:25:59.633 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@513f39c] after transaction
2014-08-15_17:25:59.633 [main] DEBUG o.s.o.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
2014-08-15_17:25:59.635 [main] DEBUG o.s.t.c.s.DirtiesContextTestExecutionListener - After test method: context [DefaultTestContext@8f72029 testClass = MyControllerTest, testInstance = a.b.c.MyControllerTest@453204e6, testMethod = testSaveObject@MyClassControllerTest, testException = org.mockito.exceptions.misusing.UnfinishedVerificationException: 
Missing method call for verify(mock) here:
-> at a.b.c.MyClassService$$FastClassBySpringCGLIB$$809f2bf.invoke(<generated>)

Example of correct verification:
    verify(mock).doSomething()

私のオディシーと研究はすでに数日間続いているので、私は本当に助けていただければ幸いです:(

ありがとう

4

1 に答える 1

2

まず、テストで Mockito を初期化していません。この投稿を読む

MockitoAnnotations.initMocks()すでに使用@RunWith(SpringJUnit4ClassRunner.class)していて、クラスで指定できるランナーは 1 つだけなので、呼び出す必要があります。

@Before
public void reset() {
    MockitoAnnotations.initMocks(this);
    // Mockito.reset(myClassServiceMock);   <= remove this line
}

このモックには @Autowired の代わりに @Mock を使用して、verify()後で呼び出すことができる Mockito モックのインスタンスを作成することもお勧めします。myClassServiceMockまた、テスト対象のクラス (つまり、コントローラー)に注入する必要があります。

@Mock
public MyClassService myClassServiceMock;

@Mock はテスト メソッドごとに新しいインスタンスを作成するため、Mockito.reset() の呼び出しを削除できます。

@Autowiredアプリケーションコンテキストから MyClassService のインスタンスを使用して取得するつもりだった場合、verify() などの Mockito メソッドを呼び出すことはできません。

@TransactionConfigurationまた、データベースにアクセスすることがないため(サービスレイヤーをモックアウトしているため)、これは不要であると予想されるため、削除できます。テストでデータベースにヒットしている場合、それは別の話ですが、提供されたコードからはわかりません。

于 2014-08-15T21:27:10.777 に答える