简体   繁体   中英

Junit test failing for the Observable pattern

I work in a small program using the Observable pattern. The code that I can't modify is provided below.

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,
}

I can modify the classes provided below:

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);
    }
}

However, I failed to pass all the tests which are below:

@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);
}

The issue is stock price increase not reflected in the code. Can anyone help me to find what is the issue here?

As we discussed on the comments, here's the working code after the updates.

Problems:

  • you were not calling notifyPriceChange at setPrice
  • exchangeCenter was not initialized/set at ObservableStockImpl

BONUS Feedback:

  • get rid of ObservableStockImpl class. You are actually duplicating though you are "extending" ObservableStock

Look for comments starting with // GT below for the updates i made:

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);
    }
}

The previous answer is correct but, he modified the test method which is not allowed. I have done with w/o any test method modification with slight changes.

The trick is in this overridden method where we register to the exchange and then move back to the mother method using the super keyword:

@Override
public void buyStock(ObservableStock observableStock) {
    observableStock.registerStockExchangeCenter(this);
    super.buyStock(observableStock);
}


class ObservableStockImpl extends ObservableStock {
    
    private ObserverStockExchangeCenter exchangeCenter;
    public final StockType stockType;
    
    public ObservableStockImpl(StockType name) {
        super(name);
        this.stockType = name;
        this.exchangeCenter = new ObserverStockExchangeCenterImpl();
    }
    
    public void notifyPriceChange(double price) {
        this.exchangeCenter.getOwnedStock().put(stockType, price);
    }
    
    public void registerStockExchangeCenter(ObserverStockExchangeCenter oc) {
        this.exchangeCenter = oc;
    }
    
    @Override
    public void setPrice(double price) {
        notifyPriceChange(price);
    }
}



class ObserverStockExchangeCenterImpl extends ObserverStockExchangeCenter {
    
    private final List<ObservableStock> observableStocks;
    
    public ObserverStockExchangeCenterImpl() {
        super();
        observableStocks = new ArrayList<>();
    }
    
    public void notifyChange(StockType type, double price) {
        
        for (ObservableStock observableStock : observableStocks) {
            if (observableStock == null) {
                continue;
            }
            
            if (observableStock.getName().equals(type)) {
                observableStock.notifyPriceChange(price);
            }
        }
    }
    
    public void observe(ObservableStock o) {
        observableStocks.add(o);
    }
    
    @Override
    public void buyStock(ObservableStock observableStock) {
        observableStock.registerStockExchangeCenter(this);
        super.buyStock(observableStock);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM