亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

“每個測試方法一個對象”的 Spring bean 范圍

“每個測試方法一個對象”的 Spring bean 范圍

明月笑刀無情 2022-12-21 13:08:19
我有一個測試實用程序,我需要每個測試方法都有一個新實例(以防止測試之間的狀態泄漏)。到目前為止,我使用的是范圍“原型”,但現在我希望能夠將該實用程序連接到另一個測試實用程序中,并且每個測試的連接實例都應該相同。這似乎是一個標準問題,所以我想知道是否有“測試方法”范圍或類似的東西?這是測試類和測試實用程序的結構:@RunWith(SpringRunner.class)@SpringBootTestpublic class MyTest {    @Autowired    private TestDriver driver;    @Autowired    private TestStateProvider state;    // ... state    // ... methods}@Component@Scope("prototype") // not right because MyTest and TestStateProvider get separate instancespublic class TestDriver {    // ...}@Componentpublic class TestStateProvider {    @Autowired    private TestDriver driver;    // ...}我知道我可以使用@Scope("singleton"),@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)但這比我需要的刷新更多——TestDriver每個測試一個新實例就足夠了。此外,這種方法容易出錯,因為所有使用 的測試TestDriver都需要知道它們也需要@DirtiesContext注釋。所以我正在尋找更好的解決方案。
查看完整描述

2 回答

?
四季花海

TA貢獻1811條經驗 獲得超5個贊

testMethod實現作用域實際上很容易:


public class TestMethodScope implements Scope {

    public static final String NAME = "testMethod";


    private Map<String, Object> scopedObjects = new HashMap<>();

    private Map<String, Runnable> destructionCallbacks = new HashMap<>();


    @Override

    public Object get(String name, ObjectFactory<?> objectFactory) {

        if (!scopedObjects.containsKey(name)) {

            scopedObjects.put(name, objectFactory.getObject());

        }

        return scopedObjects.get(name);

    }


    @Override

    public void registerDestructionCallback(String name, Runnable callback) {

        destructionCallbacks.put(name, callback);

    }


    @Override

    public Object remove(String name) {

        throw new UnsupportedOperationException();

    }


    @Override

    public String getConversationId() {

        return null;

    }


    @Override

    public Object resolveContextualObject(String key) {

        return null;

    }


    public static class TestExecutionListener implements org.springframework.test.context.TestExecutionListener {


        @Override

        public void afterTestMethod(TestContext testContext) throws Exception {

            ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext) testContext

                    .getApplicationContext();

            TestMethodScope scope = (TestMethodScope) applicationContext.getBeanFactory().getRegisteredScope(NAME);


            scope.destructionCallbacks.values().forEach(callback -> callback.run());


            scope.destructionCallbacks.clear();

            scope.scopedObjects.clear();

        }

    }


    @Component

    public static class ScopeRegistration implements BeanFactoryPostProcessor {


        @Override

        public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {

            factory.registerScope(NAME, new TestMethodScope());

        }

    }


}

@Scope("testMethod")只需注冊測試執行偵聽器,所有注釋類型的每個測試都會有一個實例:


@RunWith(SpringRunner.class)

@SpringBootTest

@TestExecutionListeners(listeners = TestMethodScope.TestExecutionListener.class, 

        mergeMode = MergeMode.MERGE_WITH_DEFAULTS)

public class MyTest {


    @Autowired

    // ... types annotated with @Scope("testMethod")


}


查看完整回答
反對 回復 2022-12-21
?
慕容森

TA貢獻1853條經驗 獲得超18個贊

我前段時間遇到了同樣的問題并得出了這個解決方案:

  1. 使用模擬

  2. 我編寫了一些方法來創建特定的 mockito 設置以向每個 mock 添加行為。

因此,使用以下方法和 bean 定義創建一個 TestConfiguration 類。

    private MockSettings createResetAfterMockSettings() {

        return MockReset.withSettings(MockReset.AFTER);

    }


    private <T> T mockClass(Class<T> classToMock) {

        return mock(classToMock, createResetAfterMockSettings());

    }

您的 bean 定義將如下所示:


@Bean

public TestDriver testDriver() {

    return mockClass(TestDriver .class);

}

MockReset.AFTER用于在運行測試方法后重置模擬。


最后添加一個TestExecutionListeners到你的測試類:


@TestExecutionListeners({ResetMocksTestExecutionListener.class})


查看完整回答
反對 回復 2022-12-21
  • 2 回答
  • 0 關注
  • 156 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號