首页 > 解决方案 > 可观察模式的 Junit 测试失败

问题描述

我使用 Observable 模式在一个小程序中工作。下面提供了我无法修改的代码。

public abstract class ObservableStock {
    
    private double price;
    private StockType name;
    
    public ObservableStock(StockType name) {
        this.name = name;
    }
    
    protected ObservableStock() {
    }
    
    public StockType getName() {
        return name;
    }
    
    public void setPrice(double price) {
        this.price = price;
    }
    
    public abstract void notifyPriceChange(double price);
    
    public abstract void registerStockExchangeCenter(ObserverStockExchangeCenter oc);
}


public abstract class ObserverStockExchangeCenter {
    
    protected Map<StockType, Double> ownedStock;
    
    public ObserverStockExchangeCenter() {
        this.ownedStock = new HashMap<>();
    }
    
    public void buyStock(ObservableStock s) {
        ownedStock.put(s.getName(), 0.0);
        System.out.println("Helo");
    }
    
    //assume we won't change values in the map
    public Map<StockType, Double> getOwnedStock() {
        return ownedStock;
    }
    
    public abstract void observe(ObservableStock o);
    
    public abstract void notifyChange(StockType type, double price);
}

public enum StockType {
    Amazon,
    Google,
}

我可以修改下面提供的类:

public class ObservableStockImpl extends ObservableStock {
    
    private ObserverStockExchangeCenter exchangeCenter;
    public final StockType stockType;
    
    public ObservableStockImpl(StockType name) {
        this.stockType = name;
    }
    
    public void notifyPriceChange(double price) {
        this.exchangeCenter.getOwnedStock().put(stockType, price);
        this.exchangeCenter.notifyChange(stockType, price);
    }
    
    public void registerStockExchangeCenter(ObserverStockExchangeCenter oc) {
        this.exchangeCenter = oc;
    }
    
    public StockType getStockType() {
        return stockType;
    }
}


public class ObserverStockExchangeCenterImpl extends ObserverStockExchangeCenter {
    
    private final List<ObservableStockImpl> observableStocks;
    
    public ObserverStockExchangeCenterImpl() {
        super();
        observableStocks = new ArrayList<>();
    }
    
    public void notifyChange(StockType type, double price) {
        
        for (ObservableStockImpl os : observableStocks) {
            if (os.getStockType().equals(type)) {
                os.setPrice(price);
                os.notifyPriceChange(price);
            }
        }
    }
    
    public void observe(ObservableStock o) {
        observableStocks.add((ObservableStockImpl) o);
    }
    
    @Override
    public void buyStock(ObservableStock s) {
        ObservableStockImpl stock = (ObservableStockImpl) s;
        ownedStock.put(stock.getStockType(), 0.0);
    }
}

但是,我未能通过以下所有测试:

@Test
public void stockPriceChangeTest(){

    ObservableStock amazonStock = new ObservableStockImpl(StockType.Amazon);
    ObserverStockExchangeCenter NYStockCenter = new ObserverStockExchangeCenterImpl();
    NYStockCenter.buyStock(amazonStock);
    Map<StockType, Double> boughtStocks = NYStockCenter.getOwnedStock();
    assertEquals(1, boughtStocks.size());
    assertEquals(0,boughtStocks.get(StockType.Amazon),0);

    amazonStock.setPrice(5);
    Map<StockType, Double> boughtStocks2 = NYStockCenter.getOwnedStock();
    assertEquals(1, boughtStocks2.size());

    // failing below
    assertEquals(5,boughtStocks2.get(StockType.Amazon),0);
}

问题是代码中没有反映股价上涨。谁能帮我找出这里的问题?

标签: javadesign-patternsjunit

解决方案


正如我们在评论中讨论的那样,这是更新后的工作代码。

问题:

  • 你没有notifyPriceChange打电话setPrice
  • exchangeCenter未在 ObservableStockImpl 初始化/设置

奖励反馈:

  • 摆脱ObservableStockImpl类。尽管您正在“扩展”,但您实际上是在复制ObservableStock

查找以下开头的评论以// GT获取我所做的更新:

package temp;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class StockListenerTest {

    @Test
    public void stockPriceChangeTest() {

        ObservableStock amazonStock = new ObservableStockImpl(StockType.Amazon);
        ObserverStockExchangeCenter NYStockCenter = new ObserverStockExchangeCenterImpl();
        
        amazonStock.registerStockExchangeCenter(NYStockCenter); // GT 1 
        
        NYStockCenter.buyStock(amazonStock);
        Map<StockType, Double> boughtStocks = NYStockCenter.getOwnedStock();
        assertEquals(1, boughtStocks.size());
        assertEquals(0, boughtStocks.get(StockType.Amazon), 0);

        amazonStock.setPrice(5);
        Map<StockType, Double> boughtStocks2 = NYStockCenter.getOwnedStock();
        assertEquals(1, boughtStocks2.size());

        // failing below
        assertEquals(5, boughtStocks2.get(StockType.Amazon), 0);
    }
}

abstract class ObservableStock {

    private double price;
    private StockType name;

    public ObservableStock(StockType name) {
        this.name = name;
    }

    protected ObservableStock() {
    }

    public StockType getName() {
        return name;
    }

    public void setPrice(double price) {
        this.price = price;
        notifyPriceChange(price); //GT 2 - called notifyPriceChange
    }

    public abstract void notifyPriceChange(double price);

    public abstract void registerStockExchangeCenter(ObserverStockExchangeCenter oc);
}


abstract class ObserverStockExchangeCenter {

    protected Map<StockType, Double> ownedStock;

    public ObserverStockExchangeCenter() {
        this.ownedStock = new HashMap<>();
    }

    public void buyStock(ObservableStock s) {
        ownedStock.put(s.getName(), 0.0);
    }

    //assume we won't change values in the map
    public Map<StockType, Double> getOwnedStock() {
        return ownedStock;
    }

    public abstract void observe(ObservableStock o);

    public abstract void notifyChange(StockType type, double price);
}

enum StockType {
    Amazon,
    Google,
}

class ObservableStockImpl extends ObservableStock {

    private ObserverStockExchangeCenter exchangeCenter;
    public final StockType stockType;

    public ObservableStockImpl(StockType name ) { 
        this.stockType = name;
    }

    public void notifyPriceChange(double price) {
        this.exchangeCenter.getOwnedStock().put(stockType, price);
        this.exchangeCenter.notifyChange(stockType, price);
    }

    public void registerStockExchangeCenter(ObserverStockExchangeCenter oc) {
        this.exchangeCenter = oc;
    }

    public StockType getStockType() {
        return stockType;
    }
}

class ObserverStockExchangeCenterImpl extends ObserverStockExchangeCenter {

    private final List<ObservableStockImpl> observableStocks;

    public ObserverStockExchangeCenterImpl() {
        super();
        observableStocks = new ArrayList<>();
    }

    public void notifyChange(StockType type, double price) {
        for (ObservableStockImpl os : observableStocks) {
            if (os.getStockType().equals(type)) {
                os.setPrice(price);
                os.notifyPriceChange(price);
            }
        }
    }

    public void observe(ObservableStock o) {
        observableStocks.add((ObservableStockImpl) o);
    }

    @Override
    public void buyStock(ObservableStock s) {
        ObservableStockImpl stock = (ObservableStockImpl) s;
        ownedStock.put(stock.getStockType(), 0.0);
    }
}


推荐阅读