私は多数の UI コンポーネントを含むプロジェクトに取り組んできました。すべてのコンポーネントは MVC パターンに基づいているため、コンポーネント (パブリック インターフェイスとファクトリ、パッケージで保護されたモデル/ビュー/コントローラー) として構造化されています。
それらを「手で」テストする - モッキング手法を使用するのは難しすぎて時間がかかります。
それで、私は Fest フレームワーク - http://fest.easytesting.org/に飛び込みました。それは簡単で、よく、仕事をします。
JMockit - http://code.google.com/p/jmockit/と Fest の両方を使用しようとすると、問題が発生します。私は、Fest が JMockit と衝突する可能性のあるいくつかのライブラリ (リフレクションとアサート) を使用していることに気付きました。
テストを実行すると、JMockit は必要なクラスをモックしません。私は以前に JMockit を使用していたので、ライブラリ間の何らかの衝突であると確信しています。モックされたクラスで生成される $Proxy$ はありません。もちろん、クラスは正しく動作しません。
完全なコンポーネントの相互作用をテストする必要があるため、モッキングが必要です!
バージョン:
Jモキット: 0.999.8
祭り:
Fest-swing 1.2.1 Fest-assert 1.4 Fest-util 1.1.6 Fest-reflect 1.2
両方のライブラリを調べて競合を探すつもりはないので、助けていただければ幸いです。
ありがとう。
アップデート:
テスト/サンプル コードは次のとおりです。
public interface SimpleControllable {
void init();
JPanel getPanel();
}
public class SimpleController implements SimpleControllable {
private final SimpleForm simpleForm;
private final SimpleModel simpleModel;
public SimpleController(
final SimpleForm simpleForm,
final SimpleModel simpleModel
) {
this.simpleForm = simpleForm;
this.simpleModel = simpleModel;
}
@Override
public void init() {
simpleForm.init();
//This works!
/*simpleForm.getTestButton().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
simpleForm.getTestButton().setText(simpleModel.getSimpleValue());
}
});*/
//This doesn't!
simpleForm.getTestButton().setText(simpleModel.getSimpleValue());
}
@Override
public JPanel getPanel() {
return simpleForm.getTestPanel();
}
}
public class SimpleModel {
private final SimpleServable simpleServable;
public SimpleModel(final SimpleServable simpleServable) {
this.simpleServable = simpleServable;
}
public String getSimpleValue() {
return simpleServable.getValue();
}
}
public interface SimpleServable {
String getValue();
}
public class SimpleService implements SimpleServable {
private String value;
@Override
public String getValue() {
return value;
}
}
public class SimpleForm {
private JButton testButton;
private JPanel testPanel;
public void init() {
testPanel.setName("testPanel");
testButton.setName("testButton");
}
public JButton getTestButton() {
return testButton;
}
public JPanel getTestPanel() {
return testPanel;
}
}
public class SimpleTest extends FestSwingJUnitTestCase {
@Mocked
private SimpleService simpleServable;
private FrameFixture window;
@Override
protected void onSetUp() {
FailOnThreadViolationRepaintManager.install();
JFrame frameUi = GuiActionRunner.execute(new GuiQuery<JFrame>() {
protected JFrame executeInEDT() {
SimpleControllable simpleControllable = getSimpleControllable();
JFrame frame = new JFrame("TEST");
frame.add(simpleControllable.getPanel());
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
return frame;
}
});
robot().settings().delayBetweenEvents(1000);
// IMPORTANT: note the call to 'robot()'
// we must use the Robot from FestSwingTestngTestCase
window = new FrameFixture(robot(), frameUi);
window.show(); // shows the frameU
}
//Should use factory, but not neccesary for test purposes...
private SimpleControllable getSimpleControllable() {
SimpleForm simpleForm = new SimpleForm();
//SimpleServable simpleServable = new SimpleService();
SimpleModel simpleModel = new SimpleModel(simpleServable);
SimpleControllable simpleControllable = new SimpleController(
simpleForm,
simpleModel
);
//Initialize the component, therein lies the problem...
simpleControllable.init();
return simpleControllable;
}
@Test
public void test() throws Exception {
//Before
new Expectations() {
{
simpleServable.getValue();
result = "TEST";
}
};
//When
//This works!
// window.panel("testPanel").button("testButton").click().requireText("TEST");
//This doesn't!
window.panel("testPanel").button("testButton").requireText("TEST");
//Then
}
}
フレームワークのせいにするのが早すぎたようです。しかし、なぜそれが機能しないのか、詳細はまだわかりません。クラスServiceはモックされており、期待を遅らせた後でも使用できるはずです。時間の問題 (コンポーネントの初期化) は理解していますが、これを「修正」する方法がわかりません。
ありがとう。
更新 2:
ありがとう、ロジェリオ。FEST でコンポーネントをテストすることはできますが、実際には JMockit を利用するわけではなく、非常に多くのメソッド (はい、わかっています - SRP ですが、このパスにとどまろうとしましょう) を持つクラスがあり、非常にメリットがあります。 JMockit などのモック フレームワークから。ここに質問を投稿する前にこれを使用したので、自分で使用して、これが私が行きたい方法ではないことを理解してください。
public class SimpleTest extends FestSwingJUnitTestCase {
//This works, and I used this mechanism before, but this is without the help of JMockit.
//If you have a lot of methods you want to mock this test turns into chaos.
public static class MockSimpleServable implements SimpleServable{
@Override
public String getValue() {
return "TEST";
}
}
// @Mocked
// private SimpleServable simpleServable;
private FrameFixture window;
@Override
protected void onSetUp() {
FailOnThreadViolationRepaintManager.install();
JFrame frameUi = GuiActionRunner.execute(new GuiQuery<JFrame>() {
protected JFrame executeInEDT() {
SimpleControllable simpleControllable = getSimpleControllable();
JFrame frame = new JFrame("TEST");
frame.add(simpleControllable.getPanel());
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
return frame;
}
});
robot().settings().delayBetweenEvents(1000);
// IMPORTANT: note the call to 'robot()'
// we must use the Robot from FestSwingTestngTestCase
window = new FrameFixture(robot(), frameUi);
window.show(); // shows the frameU
}
//Should use factory, but not neccesary for test purposes...
private SimpleControllable getSimpleControllable() {
SimpleForm simpleForm = new SimpleForm();
//SimpleServable simpleServable = new SimpleService();
SimpleServable simpleServable = new MockSimpleServable();
SimpleModel simpleModel = new SimpleModel(simpleServable);
SimpleControllable simpleControllable = new SimpleController(
simpleForm,
simpleModel
);
//Initialize the component, therein lies the problem...
simpleControllable.init();
return simpleControllable;
}
@Test
public void test() throws Exception {
//This works!
// window.panel("testPanel").button("testButton").click().requireText("TEST");
//This doesn't!
window.panel("testPanel").button("testButton").requireText("TEST");
}
}
問題は残っています - JMockit でこれをテストできる方法を誰か知っていますか? EDT 違反を忘れないでください。