0

I'm wrting a JUnit to test a threshold value, which is passed from a .properties file like:

threshold=8

And I use a spring context to apply this threshold value:

<context:property-placeholder location="classpath:test.properties"/>

<si:channel id="thresholdInputChannel"/>
<si:recipient-list-router input-channel="thresholdInputChannel" default-output-channel="nullChannel">
    <si:recipient channel = "recipientChannel" selector-expression = "${threshold} > 0"/>
</si:recipient-list-router>
...

<si:chain input-channel = "fileTransformationChannel" output-channel="endChannel">
    <si:transformer method = "transform">
        <bean class = "fileTransformer" >
            <property name = "fixedProperties">
                <map>
                    <entry key="threshold" value="${threshold}"/>
                </map>
            </property>
        </bean>
    </si:transformer>
</si:chain>
...

Before in the JUnit test, I used @ContextConfiguration(locations = {"classpath:test.properties"}) to load the context and @RunWith(SpringJUnit4ClassRunner.class) and @Autowired to get all the channels defined in context file and it worked fine. But the problem is that like this I can test at one time one single value of ${threshold} which is predefined in the test.properties.

To be able to change ${threshold} value, I tried all the ways mentioned in this answer:

  1. Use @RunWith(Parameterized.class)

    @Parameterized.Parameters
    public static List<Object[]> params() {
        return Arrays.asList(new Object[][]{
                {"0"},
                {"8"},
        });
    }
    

    but in this way I can't use injected beans any more, hence I lost the channels in JUnit.

  2. public abstract class AbstractJunitTest extends AbstractJUnit4SpringContextTests same problem with injected beans.

  3. @Value("${threshold}") private String threshold; origin value don't get erased and invoke a problem of variable type as there is selector-expression = "${threshold} > 0" in context file.

I'd like to know if there is any other possible ways to do this. Dropping the context file and creating an ApplicationConfig.class with all the beans and parameters may be a solution but not a prefered one, as the context file is really great.

By the way, the reason I have to autowire the channels in JUnit is that I have to send a local file into the fileTransformationChannel and get it transformed in some way.

Community
  • 1
  • 1
Shush
  • 77
  • 1
  • 16

1 Answers1

1

you can use org.springframework.test.context.TestContextManager for this:

Exemple:

@RunWith(Parameterized.class)
@SpringBootTest(classes = Application.class)
public class TargetClassTest {

    @Autowired
    private TargetClass instance;

    private TestContextManager testContextManager;

    String threshold;

    @Before
    public void setUpContext() throws Exception {
        this.testContextManager = new TestContextManager(getClass());
        this.testContextManager.prepareTestInstance(this);
    }


    @Parameters
    public static Collection<Object []> data() {
        return Arrays.asList(new Object[][]{
            {"0"},{"8"},
        });
    }

    public TargetClassTest(String test) {
        this.threshold = test;
    }

    @Test
    public void testSomething() throws Exception {
        String r = instance.businessMethod(threshold);
        Assert.assertEquals(threshold, r);
    }
}

In this case, it is possible after the initialization of @Before "inject" your Spring bean and use the parameterized execution to test several scenarios.

Lucas Oliveira
  • 833
  • 1
  • 10
  • 24
  • It's in which version of Spring ? I'm using 4.2.5 and there's no annotation `@SpringBootTest` – Shush Nov 23 '16 at 15:09
  • I'm using Spring Boot 1.4.2. @SpringBootTest is just class-level annotation that is used to determine how to load and configure an ApplicationContext for integration tests. – Lucas Oliveira Nov 23 '16 at 19:48