我正在研究Spring Core认证,并且我对在Spring中使用Junit有以下疑问。

我有一个示例,为我提供了以下RewardNetworkTests类

package rewards;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

import common.money.MonetaryAmount;

/**
 * A system test that verifies the components of the RewardNetwork application
 * work together to reward for dining successfully. Uses Spring to bootstrap the
 * application for use in a test environment.
 */

public class RewardNetworkTests {

    /**
     * The object being tested.
     */
    private RewardNetwork rewardNetwork;

    /**
     * Need this to enable clean shutdown at the end of the application
     */
    private AbstractApplicationContext context;

    @Before
    public void setUp() {
        // Create the test configuration for the application from one file
        context = new AnnotationConfigApplicationContext(
                TestInfrastructureConfig.class);
        // Get the bean to use to invoke the application
        rewardNetwork = context.getBean(RewardNetwork.class);
    }

    @After
    public void tearDown() throws Exception {
        // simulate the Spring bean destruction lifecycle:
        if (context != null)
            context.close();
    }

    @Test
    public void testRewardForDining() {
        // create a new dining of 100.00 charged to credit card
        // '1234123412341234' by merchant '123457890' as test input
        Dining dining = Dining.createDining("100.00", "1234123412341234",
                "1234567890");

        // call the 'rewardNetwork' to test its rewardAccountFor(Dining) method
        RewardConfirmation confirmation = rewardNetwork
                .rewardAccountFor(dining);

        // assert the expected reward confirmation results
        assertNotNull(confirmation);
        assertNotNull(confirmation.getConfirmationNumber());

        // assert an account contribution was made
        AccountContribution contribution = confirmation
                .getAccountContribution();
        assertNotNull(contribution);

        // the contribution account number should be '123456789'
        assertEquals("123456789", contribution.getAccountNumber());

        // the total contribution amount should be 8.00 (8% of 100.00)
        assertEquals(MonetaryAmount.valueOf("8.00"), contribution.getAmount());

        // the total contribution amount should have been split into 2
        // distributions
        assertEquals(2, contribution.getDistributions().size());

        // each distribution should be 4.00 (as both have a 50% allocation)
        assertEquals(MonetaryAmount.valueOf("4.00"), contribution
                .getDistribution("Annabelle").getAmount());
        assertEquals(MonetaryAmount.valueOf("4.00"), contribution
                .getDistribution("Corgan").getAmount());
    }
}


因此,此测试类包含setUp()方法,该方法从TestInfrastructureConfig.class配置类开始创建上下文:

@Before
public void setUp() {
    // Create the test configuration for the application from one file
    context = new AnnotationConfigApplicationContext(
            TestInfrastructureConfig.class);
    // Get the bean to use to invoke the application
    rewardNetwork = context.getBean(RewardNetwork.class);
}


这是TestInfrastructureConfig.class配置类的内容:

一揽子奖励;

导入org.springframework.context.annotation.Configuration;
导入org.springframework.context.annotation.Import;

导入config.RewardsConfig;

@Configuration
@Import({
    TestInfrastructureDevConfig.class,
    TestInfrastructureProductionConfig.class,
    RewardsConfig.class })
public class TestInfrastructureConfig {

    public LoggingBeanPostProcessor loggingBean(){
        return new LoggingBeanPostProcessor();
    }
}


因此,在本教程中,它告诉我,如果我删除setUp()方法,并且在执行此操作后尝试执行测试,我会得到一个红色条,因为rewardNetwork字段为null

好的,我认为这可能取决于以下事实:删除setUp()方法时,我不是从TestInfrastructureConfig.class配置类中获取上下文,而后者又导入了RewardsConfig.class配置类,该组件在该类中声明了组件扫描。用于:

@ComponentScan("rewards")


因此,该应用程序不能使用在奖励包的子包中声明的RewardNetworkImpl类(实现RewardNetwork接口),并将其标注为@Service:

@Service("rewardNetwork")
public class RewardNetworkImpl implements RewardNetwork {
    ...................................
    ...................................
    ...................................
}


好的,我认为这很清楚(还是我错过了什么?)

我的怀疑是。回到以前的测试方法:

@Test
public void testRewardForDining() {
    // create a new dining of 100.00 charged to credit card
    // '1234123412341234' by merchant '123457890' as test input
    Dining dining = Dining.createDining("100.00", "1234123412341234",
            "1234567890");

    // call the 'rewardNetwork' to test its rewardAccountFor(Dining) method
    RewardConfirmation confirmation = rewardNetwork
            .rewardAccountFor(dining);

    ...................................................
    ...................................................
    ...................................................
}


可以看出,在未建立的rewardNetwork对象上调用rewardAccountFor()方法时会引发异常,但是为什么使用调试器在Dinning dinning对象上调用createDining()方法呢?

为什么实例化该对象没有问题?

这是Dinning类代码:

public class Dining {

    private MonetaryAmount amount;

    private String creditCardNumber;

    private String merchantNumber;

    private SimpleDate date;

    /**
     * Creates a new dining, reflecting an amount that was charged to a card by a merchant on the date specified.
     * @param amount the total amount of the dining bill
     * @param creditCardNumber the number of the credit card used to pay for the dining bill
     * @param merchantNumber the merchant number of the restaurant where the dining occurred
     * @param date the date of the dining event
     */
    public Dining(MonetaryAmount amount, String creditCardNumber, String merchantNumber, SimpleDate date) {
        this.amount = amount;
        this.creditCardNumber = creditCardNumber;
        this.merchantNumber = merchantNumber;
        this.date = date;
    }

    /**
     * Creates a new dining, reflecting an amount that was charged to a credit card by a merchant on today's date. A
     * convenient static factory method.
     * @param amount the total amount of the dining bill as a string
     * @param creditCardNumber the number of the credit card used to pay for the dining bill
     * @param merchantNumber the merchant number of the restaurant where the dining occurred
     * @return the dining event
     */
    public static Dining createDining(String amount, String creditCardNumber, String merchantNumber) {
        return new Dining(MonetaryAmount.valueOf(amount), creditCardNumber, merchantNumber, SimpleDate.today());
    }

    /**
     * Creates a new dining, reflecting an amount that was charged to a credit card by a merchant on the date specified.
     * A convenient static factory method.
     * @param amount the total amount of the dining bill as a string
     * @param creditCardNumber the number of the credit card used to pay for the dining bill
     * @param merchantNumber the merchant number of the restaurant where the dining occurred
     * @param month the month of the dining event
     * @param day the day of the dining event
     * @param year the year of the dining event
     * @return the dining event
     */
    public static Dining createDining(String amount, String creditCardNumber, String merchantNumber, int month,
            int day, int year) {
        return new Dining(MonetaryAmount.valueOf(amount), creditCardNumber, merchantNumber, new SimpleDate(month, day,
                year));
    }

    /**
     * Returns the amount of this dining--the total amount of the bill that was charged to the credit card.
     */
    public MonetaryAmount getAmount() {
        return amount;
    }

    /**
     * Returns the number of the credit card used to pay for this dining. For this dining to be eligible for reward,
     * this credit card number should be associated with a valid account in the reward network.
     */
    public String getCreditCardNumber() {
        return creditCardNumber;
    }

    /**
     * Returns the merchant number of the restaurant where this dining occurred. For this dining to be eligible for
     * reward, this merchant number should be associated with a valid restaurant in the reward network.
     */
    public String getMerchantNumber() {
        return merchantNumber;
    }

    /**
     * Returns the date this dining occurred on.
     */
    public SimpleDate getDate() {
        return date;
    }

    public boolean equals(Object o) {
        if (!(o instanceof Dining)) {
            return false;
        }
        Dining other = (Dining) o;
        // value objects are equal if their attributes are equal
        return amount.equals(other.amount) && creditCardNumber.equals(other.creditCardNumber)
                && merchantNumber.equals(other.merchantNumber) && date.equals(other.date);
    }

    public int hashCode() {
        return amount.hashCode() + creditCardNumber.hashCode() + merchantNumber.hashCode() + date.hashCode();
    }

    public String toString() {
        return "Dining of " + amount + " charged to '" + creditCardNumber + "' by '" + merchantNumber + "' on " + date;
    }
}


特纳克斯

最佳答案

Dining似乎是一个类,而createDining似乎是一个static方法。无需创建Dining对象即可调用这种方法。

这等效于

System.currentTimeMillis();


Spring不参与static方法调用。

09-05 12:41