如何在Mockito

时间:2015-06-04 14:42:44

标签: java junit mockito

我正在使用Mockito编写Junit测试,该测试接受相同的参数,但在其中一个参数中使用不同的子参数。例如:

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

public class SampleMockito {

    @Mock
    private Widget widget;

    private static Machine machine;

    @BeforeClass
    public static void init() {
    machine = new Machine();
    }

    @Before
    public void setUp() {
    MockitoAnnotations.initMocks(this);
    Mockito.when(widget.doAction(Mockito.eq("Setting 1"), Mockito.any(Values.class))).thenReturn("Action 1 done.");
    Mockito.when(widget.doAction(Mockito.eq("Setting 1"), Mockito.any(Values.class))).thenReturn("Action 2 done.");
    Mockito.when(widget.doAction(Mockito.eq("Setting 2"), Mockito.any(Values.class))).thenReturn("Action 3 done.");
    Mockito.when(widget.doAction(Mockito.eq("Setting 2"), Mockito.any(Values.class))).thenReturn("Action 4 done.");

    }

    @Test
    public void testPerformAction() {
    // Some sample test code that I have not written.
    }
}

这是我的POJO

public class Widget {

    public String doAction(String param, Values values) {
    System.out.println("Do Some Irrelevant Action");
    return null;
    }
}

和工人阶级

import java.util.ArrayList;

import org.jsoup.nodes.Document;

public class Machine {

    public boolean performAction(Widget w, Document doc) {
    // Action 1
    w.doAction("Setting 1", new Values("Argument 1", "Argument 2"));
    // Action 2
    w.doAction("Setting 1", new Values("Argument 1a", new Exception("Exception message.")));
    // Action 3
    w.doAction("Setting 2", new Values("Argument 1", "Argument 2"));
    // Action 4
    w.doAction("Setting 2", new Values("Argument 1a", new Exception("Exception message.")));

    return false;
    }
}

class Values extends ArrayList<Object> {
    public Values() {

    }

    public Values(Object... vals) {
    super(vals.length);
    for (Object o : vals) {
        add(o);
    }
    }
}

正如他们目前所定义的那样,Mockito无法区分行动1和行动2以及行动3和行动4.我希望能够告诉Mockito它应该期待一定数量的字符串,或期望某种类型的异常作为Values对象的参数。在Mockito有办法做到这一点吗?还是其他一些模拟测试框架?

1 个答案:

答案 0 :(得分:0)

根据@JB Nizet的建议,我改变了我的代码以实现 argThat(...),删除了Values和ArrayList之间的继承关系,并实现了{{3}使用 argThat()

package tinkering;

import java.util.List;

import org.jsoup.nodes.Document;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import tinkering.Machine.Values;

public class SampleMockito {

    @Mock
    private Widget widget;

    private static Machine machine;
    private List<Object> vals;

    @BeforeClass
    public static void init() {
    machine = new Machine();
    }

    @Before
    public void setUp() {
    MockitoAnnotations.initMocks(this);

    }

    @SuppressWarnings("unchecked")
    @Test
    public void testPerformAction() {
    machine.performAction(widget, new Document("dumb"));
    Mockito.verify(widget).doAction(Mockito.eq("Setting 1"), (Values) Mockito.argThat(new PerformActionArgumentStringArgsMatcher()));
    Mockito.verify(widget).doAction(Mockito.eq("Setting 1"), (Values) Mockito.argThat(new PerformActionArgumentMixedArgsMatcher()));
    Mockito.verify(widget).doAction(Mockito.eq("Setting 2"), (Values) Mockito.argThat(new PerformActionArgumentStringArgsMatcher()));
    Mockito.verify(widget).doAction(Mockito.eq("Setting 2"), (Values) Mockito.argThat(new PerformActionArgumentMixedArgsMatcher()));
    }

    class PerformActionArgumentStringArgsMatcher extends ArgumentMatcher {
    @Override
    public boolean matches(Object arg) {
        if (arg instanceof Values) {
            vals = ((Values) arg).getList();
            if (vals.size() != 2)
                return false;
            if (!vals.get(0).equals("Argument 1"))
                return false;
            if (!vals.get(1).equals("Argument 2"))
                return false;
        }
        return true;
    }
    }

    class PerformActionArgumentMixedArgsMatcher extends ArgumentMatcher {
    @Override
    public boolean matches(Object arg) {
        if (arg instanceof Values) {
            vals = ((Values) arg).getList();
            if (vals.size() != 2)
                return false;
            if (!vals.get(0).equals("Argument 1a"))
                return false;
            if (!(vals.get(1) instanceof Exception) && !((Exception) vals.get(1)).getMessage().equals("Exception message."))
                return false;
        }
        return true;
    }
    }

}

对Machine.java的更改:

package tinkering;

import java.util.ArrayList;

import org.jsoup.nodes.Document;

public class Machine {

    public boolean performAction(Widget w, Document doc) {
    // Action 1
    w.doAction("Setting 1", new Values("Argument 1", "Argument 2"));
    // Action 2
    w.doAction("Setting 1", new Values("Argument 1a", new Exception("Exception message.")));
    // Action 3
    w.doAction("Setting 2", new Values("Argument 1", "Argument 2"));
    // Action 4
    w.doAction("Setting 2", new Values("Argument 1a", new Exception("Exception message.")));

    return false;
    }

    class Values {
    private ArrayList<Object> list;

    public ArrayList<Object> getList() {
        return list;
    }

    public void setList(ArrayList<Object> list) {
        this.list = list;
    }

    public Values() {

    }

    public Values(Object... vals) {
        list = new ArrayList<Object>();
        for (Object o : vals) {
            list.add(o);
        }
    }
}

编译并成功通过。