Junit测试在Observable模式下失败。

huangapple go评论74阅读模式
英文:

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?

答案1

得分: 1

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

问题:

  • 你没有在 setPrice 中调用 notifyPriceChange
  • exchangeCenterObservableStockImpl 中没有被初始化/设置

额外反馈:

  • 摆脱 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());

        // 下面的测试失败了
        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 - 调用了 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);
    }

    // 假设我们不会在映射中更改值
    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);
    }
}

如果需要进一步帮助,请随时提问。

英文:

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&lt;StockType, Double&gt; boughtStocks = NYStockCenter.getOwnedStock();
assertEquals(1, boughtStocks.size());
assertEquals(0, boughtStocks.get(StockType.Amazon), 0);
amazonStock.setPrice(5);
Map&lt;StockType, Double&gt; 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&lt;StockType, Double&gt; ownedStock;
public ObserverStockExchangeCenter() {
this.ownedStock = new HashMap&lt;&gt;();
}
public void buyStock(ObservableStock s) {
ownedStock.put(s.getName(), 0.0);
}
//assume we won&#39;t change values in the map
public Map&lt;StockType, Double&gt; 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&lt;ObservableStockImpl&gt; observableStocks;
public ObserverStockExchangeCenterImpl() {
super();
observableStocks = new ArrayList&lt;&gt;();
}
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);
}
}

答案2

得分: 0

前面的答案是正确的,但是他修改了测试方法,这是不允许的。我已经完成了,没有任何测试方法修改,只进行了轻微的更改。

关键在于这个重写的方法,在这个方法中,我们使用 super 关键字将注册到交易所的操作完成,然后回到父方法:

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

ObservableStockImpl 类示例:

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

ObserverStockExchangeCenterImpl 类示例:

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 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&lt;ObservableStock&gt; observableStocks;
public ObserverStockExchangeCenterImpl() {
super();
observableStocks = new ArrayList&lt;&gt;();
}
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);
}
}

huangapple
  • 本文由 发表于 2020年10月18日 00:34:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/64404776.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定