2016-12-07 3 views
1

Я пишу какую-нибудь функцию (тестовый слушатель) под названием SqlCounter.
Цель - подсчет запросов реального SQL во время выполнения теста.
Если этот счет больше, то специальное свойство env - тест терпит неудачу.Инъекционная логика между @Before и @Test исполнение с Spring и JUnit

Проблема в том, что у меня есть некоторая логика в моих методах @Before, в которых также выполняется много запросов. Что мне нужно - это очистить свой «счетчик SQL» фактически после ВСЕХ «до» крючков (непосредственно перед началом выполнения тестового метода).

Но все известные мне способы (org.springframework.test.context.support.AbstractTestExecutionListener: beforeTestMethod, org.junit.rules.TestWatcher: начиная, org.junit.rules.TestRule: применить) выполнить ДО @Before JUnit в :(
Помогите мне, пожалуйста;)

Update:
Я хочу, чтобы очистить этот SQL счетчик НЕ явно (в каждом @Before), но в какой-то слушатель, который должен вызываться непосредственно между @Before и @ Испытанные аннотированные методы

+0

вы можете добавить код, который очищает счетчик SQL в вашем методе @Before ПОСЛЕ установки SQL? –

+0

он реализован с помощью ttddyy/datasource-proxy (https://github.com/ttddyy/datasource-proxy), как в этой статье - https://vladmihalcea.com/2014/02/01/how-to-detect -the-n-plus-one-query-problem-upon-testing (QueryCountHolder.clear();) – Alex

ответ

2

Исполнение @Rule/@Before/@Test последовательность аннотаций в JUnit зависит от реализации Runner. Скажем SpringJUnit4ClassRunner.methodBlock или BlockJUnit4ClassRunner.methodBlock выглядит следующим образом:

Statement statement = methodInvoker(frameworkMethod, testInstance); 
statement = possiblyExpectingExceptions(frameworkMethod, testInstance, statement); 
statement = withBefores(frameworkMethod, testInstance, statement); 
... 
statement = withRules... 

Основываясь на том, что я могу предложить следующую реализацию с наиважнейшей methodInvoker и добавление новых @RightBeforeTest аннотацию

package info.test; 

import org.junit.Before; 
import org.junit.Test; 
import org.junit.internal.runners.statements.RunBefores; 
import org.junit.runner.RunWith; 
import org.junit.runners.model.FrameworkMethod; 
import org.junit.runners.model.InitializationError; 
import org.junit.runners.model.Statement; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

import static org.junit.Assert.assertEquals; 

@RunWith(JUnit4AnnotationsSequenceTest.CustomSpringJUnit4ClassRunner.class) 
public class JUnit4AnnotationsSequenceTest 
{ 
    private String value = null; 

    @Before 
    public void setUp() 
    { 
    value = "@Before.setUp"; 
    } 

    @RightBeforeTest 
    public void latestChance() 
    { 
    value = "@RightBeforeTest.latestChance"; 
    } 

    @Test 
    public void rightBeforeTestAnnotationExecutesAfterBeforeAnnotation() 
    { 
    assertEquals("@RightBeforeTest.latestChance", value); 
    } 

    public static class CustomSpringJUnit4ClassRunner extends SpringJUnit4ClassRunner 
    { 
    public CustomSpringJUnit4ClassRunner(final Class<?> clazz) throws InitializationError 
    { 
     super(clazz); 
    } 

    protected Statement methodInvoker(final FrameworkMethod method, final Object test) 
    { 
     return new RunBefores(
      super.methodInvoker(method, test), 
      getTestClass().getAnnotatedMethods(RightBeforeTest.class), 
      test); 
    } 
    } 

    @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) 
    public @interface RightBeforeTest {} 
} 

test result

+0

Это чудо! Действительно большой-большой Спасибо! ;) – Alex

Смежные вопросы