MainActivityは、リモートサーバーからUDPコールを受信できるUdpListenerという別のスレッドを最初に起動します。コンテンツ "UPDATE"を持つパケットを受信した場合、UdpListenerはMainActivityに何かを行うよう通知する必要があります。Android JUnitテストでタイミング問題が発生しました
(実際のアプリケーションでは、私のアプリケーションがリモートサーバーでリッスンしているように見えます)リモートサーバーで利用できる新しいデータがある場合は、すべてのクライアント(アプリケーション)にUDPで通知します。 HTTPを使用して新しいデータをダウンロードできることがわかります)。
これをJUnitテストでシミュレートしようとしました。テストは同様にそれがUdpListenerにUDPコールを送るようMainActivityを皮肉っ内部クラスが含まれています。良いことは、私のコンセプトの作品ということである
@RunWith(RobolectricTestRunner.class)
public class UdpListenerTest {
private MainActivityMock mainActivityMock = new MainActivityMock();
@Before
public void setUp() throws Exception {
mainActivityMock.setUpdate(false);
}
@After
public void tearDown() throws Exception {
mainActivityMock.setUpdate(false);
}
@Test
public void canNotifyObserver() throws IOException, InterruptedException {
UdpListener udpListener = new UdpListener(mainActivityMock);
udpListener.setRunning(true);
udpListener.start();
InetAddress ipAddress = InetAddress.getByName("localhost");
DatagramSocket datagramSocket = new DatagramSocket();
DatagramPacket sendPacket = new DatagramPacket("UPDATE".getBytes(), "UPDATE".length(), ipAddress, 9800);
datagramSocket.send(sendPacket);
datagramSocket.close();
assertTrue(mainActivityMock.isUpdate());
udpListener.setRunning(false);
}
private class MainActivityMock implements Observer {
private boolean update = false;
@Override
public void update() {
update = true;
}
public boolean isUpdate() {
return update;
}
public void setUpdate(boolean update) {
this.update = update;
}
}
}
:
public class UdpListener extends Thread implements Subject {
private DatagramSocket serverSocket;
private DatagramPacket receivedPacket;
private boolean running = false;
private String sentence = "";
private Observer observer;
private static final String TAG = "UdpListener";
public UdpListener(Observer o) throws SocketException {
serverSocket = new DatagramSocket(9800);
setRunning(true);
observer = o;
}
@Override
public void run() {
setName(TAG);
while (isRunning()) {
byte[] receivedData = new byte[1024];
receivedPacket = new DatagramPacket(receivedData, receivedData.length);
try {
serverSocket.receive(receivedPacket);
}
catch (IOException e) {
Log.w(TAG, e.getMessage());
}
try {
sentence = new String(receivedPacket.getData(), 0, receivedPacket.getLength(), "UTF-8");
if ("UPDATE".equals(sentence)) {
notifyObserver();
}
}
catch (UnsupportedEncodingException e) {
Log.w(TAG, e.getMessage());
}
}
}
private boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void notifyObserver() {
observer.update();
}
}
これは、対応するテストです。しかし、このテストはしません。これは、私がこの行のブレークポイントで停止してdatagramSocket.close();
を停止してから約1秒待つときにのみ実行されることを意味します。なぜこれが起こるのかは明らかです。しかし、どうすれば自動的にそれを行うことができますか?私はwait()を使うことを考えましたが、そのために他のスレッドからnotify()を呼び出さなければなりません。 CountDownLatchと同じ問題。私はそれを解決する方法がわかりませんUdpListenerを変更せずに。
が完璧です。 Btw、あなたは揮発性で正しいです。私はちょうどそれを追加した。 – Bevor